mirror of
https://github.com/corda/corda.git
synced 2025-01-27 14:49:35 +00:00
Merge pull request #767 from corda/os-merge-d3446e2
O/S merge from d3446e2
This commit is contained in:
commit
fc3dde9f66
@ -44,13 +44,13 @@ import java.lang.reflect.Field
|
|||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
import java.net.HttpURLConnection.HTTP_OK
|
import java.net.HttpURLConnection.HTTP_OK
|
||||||
|
import java.net.URI
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.nio.charset.Charset
|
import java.nio.file.CopyOption
|
||||||
import java.nio.charset.StandardCharsets.UTF_8
|
import java.nio.file.Files
|
||||||
import java.nio.file.*
|
import java.nio.file.Path
|
||||||
import java.nio.file.attribute.FileAttribute
|
import java.nio.file.Paths
|
||||||
import java.nio.file.attribute.FileTime
|
|
||||||
import java.security.KeyPair
|
import java.security.KeyPair
|
||||||
import java.security.PrivateKey
|
import java.security.PrivateKey
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -78,14 +78,6 @@ infix fun Temporal.until(endExclusive: Temporal): Duration = Duration.between(th
|
|||||||
operator fun Duration.div(divider: Long): Duration = dividedBy(divider)
|
operator fun Duration.div(divider: Long): Duration = dividedBy(divider)
|
||||||
operator fun Duration.times(multiplicand: Long): Duration = multipliedBy(multiplicand)
|
operator fun Duration.times(multiplicand: Long): Duration = multipliedBy(multiplicand)
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows you to write code like: Paths.get("someDir") / "subdir" / "filename" but using the Paths API to avoid platform
|
|
||||||
* separator problems.
|
|
||||||
*/
|
|
||||||
operator fun Path.div(other: String): Path = resolve(other)
|
|
||||||
|
|
||||||
operator fun String.div(other: String): Path = Paths.get(this) / other
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the single element matching the given [predicate], or `null` if the collection is empty, or throws exception
|
* Returns the single element matching the given [predicate], or `null` if the collection is empty, or throws exception
|
||||||
* if more than one element was found.
|
* if more than one element was found.
|
||||||
@ -130,43 +122,6 @@ fun <T> List<T>.indexOfOrThrow(item: T): Int {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Path.createDirectory(vararg attrs: FileAttribute<*>): Path = Files.createDirectory(this, *attrs)
|
|
||||||
fun Path.createDirectories(vararg attrs: FileAttribute<*>): Path = Files.createDirectories(this, *attrs)
|
|
||||||
fun Path.exists(vararg options: LinkOption): Boolean = Files.exists(this, *options)
|
|
||||||
fun Path.copyToDirectory(targetDir: Path, vararg options: CopyOption): Path {
|
|
||||||
require(targetDir.isDirectory()) { "$targetDir is not a directory" }
|
|
||||||
val targetFile = targetDir.resolve(fileName)
|
|
||||||
Files.copy(this, targetFile, *options)
|
|
||||||
return targetFile
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Path.moveTo(target: Path, vararg options: CopyOption): Path = Files.move(this, target, *options)
|
|
||||||
fun Path.isRegularFile(vararg options: LinkOption): Boolean = Files.isRegularFile(this, *options)
|
|
||||||
fun Path.isDirectory(vararg options: LinkOption): Boolean = Files.isDirectory(this, *options)
|
|
||||||
inline val Path.size: Long get() = Files.size(this)
|
|
||||||
fun Path.lastModifiedTime(vararg options: LinkOption): FileTime = Files.getLastModifiedTime(this, *options)
|
|
||||||
inline fun <R> Path.list(block: (Stream<Path>) -> R): R = Files.list(this).use(block)
|
|
||||||
fun Path.deleteIfExists(): Boolean = Files.deleteIfExists(this)
|
|
||||||
fun Path.reader(charset: Charset = UTF_8): BufferedReader = Files.newBufferedReader(this, charset)
|
|
||||||
fun Path.writer(charset: Charset = UTF_8, vararg options: OpenOption): BufferedWriter = Files.newBufferedWriter(this, charset, *options)
|
|
||||||
fun Path.readAll(): ByteArray = Files.readAllBytes(this)
|
|
||||||
inline fun <R> Path.read(vararg options: OpenOption, block: (InputStream) -> R): R = Files.newInputStream(this, *options).use(block)
|
|
||||||
inline fun Path.write(createDirs: Boolean = false, vararg options: OpenOption = emptyArray(), block: (OutputStream) -> Unit) {
|
|
||||||
if (createDirs) {
|
|
||||||
normalize().parent?.createDirectories()
|
|
||||||
}
|
|
||||||
Files.newOutputStream(this, *options).use(block)
|
|
||||||
}
|
|
||||||
|
|
||||||
inline fun <R> Path.readLines(charset: Charset = UTF_8, block: (Stream<String>) -> R): R = Files.lines(this, charset).use(block)
|
|
||||||
fun Path.readAllLines(charset: Charset = UTF_8): List<String> = Files.readAllLines(this, charset)
|
|
||||||
fun Path.writeLines(lines: Iterable<CharSequence>, charset: Charset = UTF_8, vararg options: OpenOption): Path = Files.write(this, lines, charset, *options)
|
|
||||||
|
|
||||||
inline fun <reified T : Any> Path.readObject(): T = readAll().deserialize()
|
|
||||||
|
|
||||||
/** Calculate the hash of the contents of this file. */
|
|
||||||
val Path.hash: SecureHash get() = read { it.hash() }
|
|
||||||
|
|
||||||
fun InputStream.copyTo(target: Path, vararg options: CopyOption): Long = Files.copy(this, target, *options)
|
fun InputStream.copyTo(target: Path, vararg options: CopyOption): Long = Files.copy(this, target, *options)
|
||||||
|
|
||||||
/** Same as [InputStream.readBytes] but also closes the stream. */
|
/** Same as [InputStream.readBytes] but also closes the stream. */
|
||||||
@ -361,6 +316,10 @@ fun TransactionBuilder.toLedgerTransaction(services: ServicesForResolution, seri
|
|||||||
/** Convenience method to get the package name of a class literal. */
|
/** Convenience method to get the package name of a class literal. */
|
||||||
val KClass<*>.packageName: String get() = java.`package`.name
|
val KClass<*>.packageName: String get() = java.`package`.name
|
||||||
|
|
||||||
|
fun URI.toPath(): Path = Paths.get(this)
|
||||||
|
|
||||||
|
fun URL.toPath(): Path = toURI().toPath()
|
||||||
|
|
||||||
fun URL.openHttpConnection(): HttpURLConnection = openConnection() as HttpURLConnection
|
fun URL.openHttpConnection(): HttpURLConnection = openConnection() as HttpURLConnection
|
||||||
|
|
||||||
fun URL.post(serializedData: OpaqueBytes, vararg properties: Pair<String, String>): ByteArray {
|
fun URL.post(serializedData: OpaqueBytes, vararg properties: Pair<String, String>): ByteArray {
|
||||||
|
176
core/src/main/kotlin/net/corda/core/internal/PathUtils.kt
Normal file
176
core/src/main/kotlin/net/corda/core/internal/PathUtils.kt
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
package net.corda.core.internal
|
||||||
|
|
||||||
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.serialization.deserialize
|
||||||
|
import java.io.*
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
import java.nio.charset.StandardCharsets.UTF_8
|
||||||
|
import java.nio.file.*
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes
|
||||||
|
import java.nio.file.attribute.FileAttribute
|
||||||
|
import java.nio.file.attribute.FileTime
|
||||||
|
import java.util.stream.Stream
|
||||||
|
import kotlin.streams.toList
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows you to write code like: Paths.get("someDir") / "subdir" / "filename" but using the Paths API to avoid platform
|
||||||
|
* separator problems.
|
||||||
|
* @see Path.resolve
|
||||||
|
*/
|
||||||
|
operator fun Path.div(other: String): Path = resolve(other)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows you to write code like: "someDir" / "subdir" / "filename" but using the Paths API to avoid platform
|
||||||
|
* separator problems.
|
||||||
|
* @see Path.resolve
|
||||||
|
*/
|
||||||
|
operator fun String.div(other: String): Path = Paths.get(this) / other
|
||||||
|
|
||||||
|
/** @see Files.createFile */
|
||||||
|
fun Path.createFile(vararg attrs: FileAttribute<*>): Path = Files.createFile(this, *attrs)
|
||||||
|
|
||||||
|
/** @see Files.createDirectory */
|
||||||
|
fun Path.createDirectory(vararg attrs: FileAttribute<*>): Path = Files.createDirectory(this, *attrs)
|
||||||
|
|
||||||
|
/** @see Files.createDirectories */
|
||||||
|
fun Path.createDirectories(vararg attrs: FileAttribute<*>): Path = Files.createDirectories(this, *attrs)
|
||||||
|
|
||||||
|
/** @see Files.exists */
|
||||||
|
fun Path.exists(vararg options: LinkOption): Boolean = Files.exists(this, *options)
|
||||||
|
|
||||||
|
/** Copy the file into the target directory using [Files.copy]. */
|
||||||
|
fun Path.copyToDirectory(targetDir: Path, vararg options: CopyOption): Path {
|
||||||
|
require(targetDir.isDirectory()) { "$targetDir is not a directory" }
|
||||||
|
val targetFile = targetDir.resolve(fileName)
|
||||||
|
Files.copy(this, targetFile, *options)
|
||||||
|
return targetFile
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @see Files.copy */
|
||||||
|
fun Path.copyTo(target: Path, vararg options: CopyOption): Path = Files.copy(this, target, *options)
|
||||||
|
|
||||||
|
/** @see Files.move */
|
||||||
|
fun Path.moveTo(target: Path, vararg options: CopyOption): Path = Files.move(this, target, *options)
|
||||||
|
|
||||||
|
/** See overload of [Files.copy] which takes in an [InputStream]. */
|
||||||
|
fun Path.copyTo(out: OutputStream): Long = Files.copy(this, out)
|
||||||
|
|
||||||
|
/** @see Files.isRegularFile */
|
||||||
|
fun Path.isRegularFile(vararg options: LinkOption): Boolean = Files.isRegularFile(this, *options)
|
||||||
|
|
||||||
|
/** @see Files.isReadable */
|
||||||
|
inline val Path.isReadable: Boolean get() = Files.isReadable(this)
|
||||||
|
|
||||||
|
/** @see Files.size */
|
||||||
|
inline val Path.size: Long get() = Files.size(this)
|
||||||
|
|
||||||
|
/** @see Files.getLastModifiedTime */
|
||||||
|
fun Path.lastModifiedTime(vararg options: LinkOption): FileTime = Files.getLastModifiedTime(this, *options)
|
||||||
|
|
||||||
|
/** @see Files.isDirectory */
|
||||||
|
fun Path.isDirectory(vararg options: LinkOption): Boolean = Files.isDirectory(this, *options)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as [Files.list] except it also closes the [Stream].
|
||||||
|
* @return the output of [block]
|
||||||
|
*/
|
||||||
|
inline fun <R> Path.list(block: (Stream<Path>) -> R): R = Files.list(this).use(block)
|
||||||
|
|
||||||
|
/** Same as [list] but materialises all the entiries into a list. */
|
||||||
|
fun Path.list(): List<Path> = list { it.toList() }
|
||||||
|
|
||||||
|
/** @see Files.walk */
|
||||||
|
inline fun <R> Path.walk(maxDepth: Int = Int.MAX_VALUE, vararg options: FileVisitOption, block: (Stream<Path>) -> R): R {
|
||||||
|
return Files.walk(this, maxDepth, *options).use(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @see Files.delete */
|
||||||
|
fun Path.delete(): Unit = Files.delete(this)
|
||||||
|
|
||||||
|
/** @see Files.deleteIfExists */
|
||||||
|
fun Path.deleteIfExists(): Boolean = Files.deleteIfExists(this)
|
||||||
|
|
||||||
|
/** Deletes this path (if it exists) and if it's a directory, all its child paths recursively. */
|
||||||
|
fun Path.deleteRecursively() {
|
||||||
|
if (!exists()) return
|
||||||
|
Files.walkFileTree(this, object : SimpleFileVisitor<Path>() {
|
||||||
|
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
|
||||||
|
file.delete()
|
||||||
|
return FileVisitResult.CONTINUE
|
||||||
|
}
|
||||||
|
override fun postVisitDirectory(dir: Path, exception: IOException?): FileVisitResult {
|
||||||
|
dir.delete()
|
||||||
|
return FileVisitResult.CONTINUE
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @see Files.newOutputStream */
|
||||||
|
fun Path.outputStream(vararg options: OpenOption): OutputStream = Files.newOutputStream(this, *options)
|
||||||
|
|
||||||
|
/** @see Files.newInputStream */
|
||||||
|
fun Path.inputStream(vararg options: OpenOption): InputStream = Files.newInputStream(this, *options)
|
||||||
|
|
||||||
|
/** @see Files.newBufferedReader */
|
||||||
|
fun Path.reader(charset: Charset = UTF_8): BufferedReader = Files.newBufferedReader(this, charset)
|
||||||
|
|
||||||
|
/** @see Files.newBufferedWriter */
|
||||||
|
fun Path.writer(charset: Charset = UTF_8, vararg options: OpenOption): BufferedWriter {
|
||||||
|
return Files.newBufferedWriter(this, charset, *options)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @see Files.readAllBytes */
|
||||||
|
fun Path.readAll(): ByteArray = Files.readAllBytes(this)
|
||||||
|
|
||||||
|
/** Read in this entire file as a string using the given encoding. */
|
||||||
|
fun Path.readText(charset: Charset = UTF_8): String = reader(charset).use(Reader::readText)
|
||||||
|
|
||||||
|
/** @see Files.write */
|
||||||
|
fun Path.write(bytes: ByteArray, vararg options: OpenOption): Path = Files.write(this, bytes, *options)
|
||||||
|
|
||||||
|
/** Write the given string to this file. */
|
||||||
|
fun Path.writeText(text: String, charset: Charset = UTF_8, vararg options: OpenOption) {
|
||||||
|
writer(charset, *options).use { it.write(text) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as [inputStream] except it also closes the [InputStream].
|
||||||
|
* @return the output of [block]
|
||||||
|
*/
|
||||||
|
inline fun <R> Path.read(vararg options: OpenOption, block: (InputStream) -> R): R = inputStream(*options).use(block)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as [outputStream] except it also closes the [OutputStream].
|
||||||
|
* @param createDirs if true then the parent directory of this file is created. Defaults to false.
|
||||||
|
* @return the output of [block]
|
||||||
|
*/
|
||||||
|
inline fun Path.write(createDirs: Boolean = false, vararg options: OpenOption = emptyArray(), block: (OutputStream) -> Unit) {
|
||||||
|
if (createDirs) {
|
||||||
|
normalize().parent?.createDirectories()
|
||||||
|
}
|
||||||
|
outputStream(*options).use(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as [Files.lines] except it also closes the [Stream]
|
||||||
|
* @return the output of [block]
|
||||||
|
*/
|
||||||
|
inline fun <R> Path.readLines(charset: Charset = UTF_8, block: (Stream<String>) -> R): R {
|
||||||
|
return Files.lines(this, charset).use(block)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @see Files.readAllLines */
|
||||||
|
fun Path.readAllLines(charset: Charset = UTF_8): List<String> = Files.readAllLines(this, charset)
|
||||||
|
|
||||||
|
fun Path.writeLines(lines: Iterable<CharSequence>, charset: Charset = UTF_8, vararg options: OpenOption): Path {
|
||||||
|
return Files.write(this, lines, charset, *options)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read in this file as an AMQP serialised blob of type [T].
|
||||||
|
* @see [deserialize]
|
||||||
|
*/
|
||||||
|
inline fun <reified T : Any> Path.readObject(): T = readAll().deserialize()
|
||||||
|
|
||||||
|
/** Calculate the hash of the contents of this file. */
|
||||||
|
inline val Path.hash: SecureHash get() = read { it.hash() }
|
@ -12,11 +12,11 @@ package net.corda.core.internal.cordapp
|
|||||||
|
|
||||||
import net.corda.core.cordapp.Cordapp
|
import net.corda.core.cordapp.Cordapp
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.internal.toPath
|
||||||
import net.corda.core.schemas.MappedSchema
|
import net.corda.core.schemas.MappedSchema
|
||||||
import net.corda.core.serialization.SerializationCustomSerializer
|
import net.corda.core.serialization.SerializationCustomSerializer
|
||||||
import net.corda.core.serialization.SerializationWhitelist
|
import net.corda.core.serialization.SerializationWhitelist
|
||||||
import net.corda.core.serialization.SerializeAsToken
|
import net.corda.core.serialization.SerializeAsToken
|
||||||
import java.io.File
|
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
data class CordappImpl(
|
data class CordappImpl(
|
||||||
@ -30,7 +30,7 @@ data class CordappImpl(
|
|||||||
override val serializationCustomSerializers: List<SerializationCustomSerializer<*, *>>,
|
override val serializationCustomSerializers: List<SerializationCustomSerializer<*, *>>,
|
||||||
override val customSchemas: Set<MappedSchema>,
|
override val customSchemas: Set<MappedSchema>,
|
||||||
override val jarPath: URL) : Cordapp {
|
override val jarPath: URL) : Cordapp {
|
||||||
override val name: String = File(jarPath.toURI()).name.removeSuffix(".jar")
|
override val name: String = jarPath.toPath().fileName.toString().removeSuffix(".jar")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An exhaustive list of all classes relevant to the node within this CorDapp
|
* An exhaustive list of all classes relevant to the node within this CorDapp
|
||||||
|
@ -12,13 +12,16 @@ package net.corda.core.internal
|
|||||||
|
|
||||||
import net.corda.testing.core.ALICE_NAME
|
import net.corda.testing.core.ALICE_NAME
|
||||||
import net.corda.testing.core.BOB_NAME
|
import net.corda.testing.core.BOB_NAME
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.AfterClass
|
import org.junit.AfterClass
|
||||||
import org.junit.BeforeClass
|
import org.junit.BeforeClass
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
|
import kotlin.streams.toList
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class AbstractAttachmentTest {
|
class AbstractAttachmentTest {
|
||||||
@ -46,23 +49,23 @@ class AbstractAttachmentTest {
|
|||||||
(dir / "_signable3").writeLines(listOf("signable3"))
|
(dir / "_signable3").writeLines(listOf("signable3"))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun load(name: String) = object : AbstractAttachment({ (dir / name).readAll() }) {
|
private fun load(name: String) = object : AbstractAttachment((dir / name)::readAll) {
|
||||||
override val id get() = throw UnsupportedOperationException()
|
override val id get() = throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun afterClass() {
|
fun afterClass() {
|
||||||
dir.toFile().deleteRecursively()
|
dir.deleteRecursively()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun tearDown() {
|
fun tearDown() {
|
||||||
dir.toFile().listFiles().forEach {
|
dir.list {
|
||||||
if (!it.name.startsWith("_")) it.deleteRecursively()
|
it.filter { !it.fileName.toString().startsWith("_") }.forEach(Path::deleteRecursively)
|
||||||
}
|
}
|
||||||
assertEquals(5, dir.toFile().listFiles().size)
|
assertThat(dir.list()).hasSize(5)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -0,0 +1,62 @@
|
|||||||
|
package net.corda.core.internal
|
||||||
|
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.rules.TemporaryFolder
|
||||||
|
|
||||||
|
class PathUtilsTest {
|
||||||
|
@Rule
|
||||||
|
@JvmField
|
||||||
|
val tempFolder = TemporaryFolder()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `deleteRecursively - non-existent path`() {
|
||||||
|
val path = tempFolder.root.toPath() / "non-existent"
|
||||||
|
path.deleteRecursively()
|
||||||
|
assertThat(path).doesNotExist()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `deleteRecursively - file`() {
|
||||||
|
val file = (tempFolder.root.toPath() / "file").createFile()
|
||||||
|
file.deleteRecursively()
|
||||||
|
assertThat(file).doesNotExist()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `deleteRecursively - empty folder`() {
|
||||||
|
val emptyDir = (tempFolder.root.toPath() / "empty").createDirectories()
|
||||||
|
emptyDir.deleteRecursively()
|
||||||
|
assertThat(emptyDir).doesNotExist()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `deleteRecursively - dir with single file`() {
|
||||||
|
val dir = (tempFolder.root.toPath() / "dir").createDirectories()
|
||||||
|
(dir / "file").createFile()
|
||||||
|
dir.deleteRecursively()
|
||||||
|
assertThat(dir).doesNotExist()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `deleteRecursively - nested single file`() {
|
||||||
|
val dir = (tempFolder.root.toPath() / "dir").createDirectories()
|
||||||
|
val dir2 = (dir / "dir2").createDirectories()
|
||||||
|
(dir2 / "file").createFile()
|
||||||
|
dir.deleteRecursively()
|
||||||
|
assertThat(dir).doesNotExist()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `deleteRecursively - complex`() {
|
||||||
|
val dir = (tempFolder.root.toPath() / "dir").createDirectories()
|
||||||
|
(dir / "file1").createFile()
|
||||||
|
val dir2 = (dir / "dir2").createDirectories()
|
||||||
|
(dir2 / "file2").createFile()
|
||||||
|
(dir2 / "file3").createFile()
|
||||||
|
(dir2 / "dir3").createDirectories()
|
||||||
|
dir.deleteRecursively()
|
||||||
|
assertThat(dir).doesNotExist()
|
||||||
|
}
|
||||||
|
}
|
@ -10,8 +10,8 @@
|
|||||||
|
|
||||||
package net.corda.docs
|
package net.corda.docs
|
||||||
|
|
||||||
|
import net.corda.core.internal.toPath
|
||||||
import net.corda.node.services.config.ConfigHelper
|
import net.corda.node.services.config.ConfigHelper
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
|
||||||
import net.corda.node.services.config.parseAsNodeConfiguration
|
import net.corda.node.services.config.parseAsNodeConfiguration
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@ -25,7 +25,7 @@ class ExampleConfigTest {
|
|||||||
configFilenames.forEach {
|
configFilenames.forEach {
|
||||||
println("Checking $it")
|
println("Checking $it")
|
||||||
val configFileResource = ExampleConfigTest::class.java.classLoader.getResource(it)
|
val configFileResource = ExampleConfigTest::class.java.classLoader.getResource(it)
|
||||||
val config = loadConfig(Paths.get(configFileResource.toURI()))
|
val config = loadConfig(configFileResource.toPath())
|
||||||
// Force the config fields as they are resolved lazily
|
// Force the config fields as they are resolved lazily
|
||||||
config.javaClass.kotlin.declaredMemberProperties.forEach { member ->
|
config.javaClass.kotlin.declaredMemberProperties.forEach { member ->
|
||||||
if (member.visibility == KVisibility.PUBLIC) {
|
if (member.visibility == KVisibility.PUBLIC) {
|
||||||
@ -37,7 +37,7 @@ class ExampleConfigTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `example node_confs parses fine`() {
|
fun `example node_confs parses fine`() {
|
||||||
readAndCheckConfigurations<NodeConfiguration>(
|
readAndCheckConfigurations(
|
||||||
"example-node.conf",
|
"example-node.conf",
|
||||||
"example-out-of-process-verifier-node.conf"
|
"example-out-of-process-verifier-node.conf"
|
||||||
) {
|
) {
|
||||||
|
@ -13,6 +13,8 @@ package net.corda.behave
|
|||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
|
// TODO Most of these are available in corda core
|
||||||
|
|
||||||
val Int.millisecond: Duration
|
val Int.millisecond: Duration
|
||||||
get() = Duration.ofMillis(this.toLong())
|
get() = Duration.ofMillis(this.toLong())
|
||||||
|
|
||||||
|
@ -10,15 +10,12 @@
|
|||||||
|
|
||||||
package net.corda.behave.file
|
package net.corda.behave.file
|
||||||
|
|
||||||
import java.io.File
|
import java.nio.file.Path
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
val currentDirectory: File
|
val currentDirectory: Path
|
||||||
get() = File(System.getProperty("user.dir"))
|
get() = Paths.get(System.getProperty("user.dir"))
|
||||||
|
|
||||||
// location of Corda distributions and Drivers dependencies
|
// location of Corda distributions and Drivers dependencies
|
||||||
val stagingRoot: File
|
val stagingRoot: Path
|
||||||
get() = if (System.getProperty("STAGING_ROOT") != null)
|
get() = System.getProperty("STAGING_ROOT")?.let { Paths.get(it) } ?: currentDirectory
|
||||||
File(System.getProperty("STAGING_ROOT"))
|
|
||||||
else currentDirectory
|
|
||||||
|
|
||||||
operator fun File.div(relative: String): File = this.resolve(relative)
|
|
||||||
|
@ -10,10 +10,13 @@
|
|||||||
|
|
||||||
package net.corda.behave.file
|
package net.corda.behave.file
|
||||||
|
|
||||||
import java.io.File
|
import net.corda.core.internal.list
|
||||||
|
import net.corda.core.internal.readText
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.streams.toList
|
||||||
|
|
||||||
class LogSource(
|
class LogSource(
|
||||||
private val directory: File,
|
private val directory: Path,
|
||||||
filePattern: String? = ".*\\.log",
|
filePattern: String? = ".*\\.log",
|
||||||
private val filePatternUsedForExclusion: Boolean = false
|
private val filePatternUsedForExclusion: Boolean = false
|
||||||
) {
|
) {
|
||||||
@ -21,7 +24,7 @@ class LogSource(
|
|||||||
private val fileRegex = Regex(filePattern ?: ".*")
|
private val fileRegex = Regex(filePattern ?: ".*")
|
||||||
|
|
||||||
data class MatchedLogContent(
|
data class MatchedLogContent(
|
||||||
val filename: File,
|
val filename: Path,
|
||||||
val contents: String
|
val contents: String
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,10 +34,12 @@ class LogSource(
|
|||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
val logFiles = directory.listFiles({ file ->
|
val logFiles = directory.list {
|
||||||
(!filePatternUsedForExclusion && file.name.matches(fileRegex)) ||
|
it.filter {
|
||||||
(filePatternUsedForExclusion && !file.name.matches(fileRegex))
|
(!filePatternUsedForExclusion && it.fileName.toString().matches(fileRegex)) ||
|
||||||
})
|
(filePatternUsedForExclusion && !it.fileName.toString().matches(fileRegex))
|
||||||
|
}.toList()
|
||||||
|
}
|
||||||
val result = mutableListOf<MatchedLogContent>()
|
val result = mutableListOf<MatchedLogContent>()
|
||||||
for (file in logFiles) {
|
for (file in logFiles) {
|
||||||
val contents = file.readText()
|
val contents = file.readText()
|
||||||
|
@ -13,5 +13,7 @@ package net.corda.behave.logging
|
|||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
// TODO Already available in corda core
|
||||||
|
|
||||||
inline fun <reified T> getLogger(): Logger =
|
inline fun <reified T> getLogger(): Logger =
|
||||||
LoggerFactory.getLogger(T::class.java)
|
LoggerFactory.getLogger(T::class.java)
|
||||||
|
@ -13,7 +13,6 @@ package net.corda.behave.network
|
|||||||
import net.corda.behave.database.DatabaseType
|
import net.corda.behave.database.DatabaseType
|
||||||
import net.corda.behave.file.LogSource
|
import net.corda.behave.file.LogSource
|
||||||
import net.corda.behave.file.currentDirectory
|
import net.corda.behave.file.currentDirectory
|
||||||
import net.corda.behave.file.div
|
|
||||||
import net.corda.behave.file.stagingRoot
|
import net.corda.behave.file.stagingRoot
|
||||||
import net.corda.behave.logging.getLogger
|
import net.corda.behave.logging.getLogger
|
||||||
import net.corda.behave.minutes
|
import net.corda.behave.minutes
|
||||||
@ -22,19 +21,20 @@ import net.corda.behave.node.Node
|
|||||||
import net.corda.behave.node.configuration.NotaryType
|
import net.corda.behave.node.configuration.NotaryType
|
||||||
import net.corda.behave.process.JarCommand
|
import net.corda.behave.process.JarCommand
|
||||||
import net.corda.core.CordaException
|
import net.corda.core.CordaException
|
||||||
|
import net.corda.core.internal.*
|
||||||
import org.apache.commons.io.FileUtils
|
import org.apache.commons.io.FileUtils
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.io.File
|
import java.nio.file.Path
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.ZoneId
|
import java.time.ZoneOffset.UTC
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
class Network private constructor(
|
class Network private constructor(
|
||||||
private val nodes: Map<String, Node>,
|
private val nodes: Map<String, Node>,
|
||||||
private val targetDirectory: File,
|
private val targetDirectory: Path,
|
||||||
private val timeout: Duration = 2.minutes
|
private val timeout: Duration = 2.minutes
|
||||||
) : Closeable, Iterable<Node> {
|
) : Closeable, Iterable<Node> {
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ class Network private constructor(
|
|||||||
private var hasError = false
|
private var hasError = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
FileUtils.forceMkdir(targetDirectory)
|
targetDirectory.createDirectories()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Builder internal constructor(
|
class Builder internal constructor(
|
||||||
@ -58,10 +58,10 @@ class Network private constructor(
|
|||||||
|
|
||||||
private val startTime = DateTimeFormatter
|
private val startTime = DateTimeFormatter
|
||||||
.ofPattern("yyyyMMdd-HHmmss")
|
.ofPattern("yyyyMMdd-HHmmss")
|
||||||
.withZone(ZoneId.of("UTC"))
|
.withZone(UTC)
|
||||||
.format(Instant.now())
|
.format(Instant.now())
|
||||||
|
|
||||||
private val directory = currentDirectory / "build/runs/$startTime"
|
private val directory = currentDirectory / "build" / "runs" / startTime
|
||||||
|
|
||||||
fun addNode(
|
fun addNode(
|
||||||
name: String,
|
name: String,
|
||||||
@ -102,12 +102,11 @@ class Network private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun copyDatabaseDrivers() {
|
fun copyDatabaseDrivers() {
|
||||||
val driverDirectory = targetDirectory / "libs"
|
val driverDirectory = (targetDirectory / "libs").createDirectories()
|
||||||
log.info("Copying database drivers from $stagingRoot/deps/drivers to $driverDirectory")
|
log.info("Copying database drivers from $stagingRoot/deps/drivers to $driverDirectory")
|
||||||
FileUtils.forceMkdir(driverDirectory)
|
|
||||||
FileUtils.copyDirectory(
|
FileUtils.copyDirectory(
|
||||||
stagingRoot / "deps/drivers",
|
(stagingRoot / "deps" / "drivers").toFile(),
|
||||||
driverDirectory
|
driverDirectory.toFile()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +159,7 @@ class Network private constructor(
|
|||||||
error("Failed to bootstrap network") {
|
error("Failed to bootstrap network") {
|
||||||
val matches = LogSource(targetDirectory)
|
val matches = LogSource(targetDirectory)
|
||||||
.find(".*[Ee]xception.*")
|
.find(".*[Ee]xception.*")
|
||||||
.groupBy { it.filename.absolutePath }
|
.groupBy { it.filename.toAbsolutePath() }
|
||||||
for (match in matches) {
|
for (match in matches) {
|
||||||
log.info("Log(${match.key}):\n${match.value.joinToString("\n") { it.contents }}")
|
log.info("Log(${match.key}):\n${match.value.joinToString("\n") { it.contents }}")
|
||||||
}
|
}
|
||||||
@ -174,30 +173,17 @@ class Network private constructor(
|
|||||||
try {
|
try {
|
||||||
if (!hasError || CLEANUP_ON_ERROR) {
|
if (!hasError || CLEANUP_ON_ERROR) {
|
||||||
log.info("Cleaning up runtime ...")
|
log.info("Cleaning up runtime ...")
|
||||||
FileUtils.deleteDirectory(targetDirectory)
|
targetDirectory.deleteRecursively()
|
||||||
} else {
|
} else {
|
||||||
log.info("Deleting temporary files, but retaining logs and config ...")
|
log.info("Deleting temporary files, but retaining logs and config ...")
|
||||||
for (node in nodes.values.map { it.config.name }) {
|
for (node in nodes.values) {
|
||||||
val nodeFolder = targetDirectory / node
|
val nodeDir = targetDirectory / node.config.name
|
||||||
FileUtils.deleteDirectory(nodeFolder / "additional-node-infos")
|
nodeDir.list { paths -> paths
|
||||||
FileUtils.deleteDirectory(nodeFolder / "artemis")
|
.filter { it.fileName.toString() !in setOf("logs", "node.conf") }
|
||||||
FileUtils.deleteDirectory(nodeFolder / "certificates")
|
.forEach(Path::deleteRecursively)
|
||||||
FileUtils.deleteDirectory(nodeFolder / "cordapps")
|
|
||||||
FileUtils.deleteDirectory(nodeFolder / "shell-commands")
|
|
||||||
FileUtils.deleteDirectory(nodeFolder / "sshkey")
|
|
||||||
FileUtils.deleteQuietly(nodeFolder / "corda.jar")
|
|
||||||
FileUtils.deleteQuietly(nodeFolder / "network-parameters")
|
|
||||||
FileUtils.deleteQuietly(nodeFolder / "persistence.mv.db")
|
|
||||||
FileUtils.deleteQuietly(nodeFolder / "process-id")
|
|
||||||
|
|
||||||
for (nodeInfo in nodeFolder.listFiles({
|
|
||||||
file -> file.name.matches(Regex("nodeInfo-.*"))
|
|
||||||
})) {
|
|
||||||
FileUtils.deleteQuietly(nodeInfo)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileUtils.deleteDirectory(targetDirectory / "libs")
|
listOf("libs", ".cache").forEach { (targetDirectory / it).deleteRecursively() }
|
||||||
FileUtils.deleteDirectory(targetDirectory / ".cache")
|
|
||||||
}
|
}
|
||||||
log.info("Network was shut down successfully")
|
log.info("Network was shut down successfully")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
|
@ -10,13 +10,15 @@
|
|||||||
|
|
||||||
package net.corda.behave.node
|
package net.corda.behave.node
|
||||||
|
|
||||||
import net.corda.behave.file.div
|
|
||||||
import net.corda.behave.file.stagingRoot
|
import net.corda.behave.file.stagingRoot
|
||||||
import net.corda.behave.logging.getLogger
|
import net.corda.behave.logging.getLogger
|
||||||
import net.corda.behave.service.Service
|
import net.corda.behave.service.Service
|
||||||
import org.apache.commons.io.FileUtils
|
import net.corda.core.internal.copyTo
|
||||||
import java.io.File
|
import net.corda.core.internal.createDirectories
|
||||||
|
import net.corda.core.internal.div
|
||||||
|
import net.corda.core.internal.exists
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Corda distribution.
|
* Corda distribution.
|
||||||
@ -31,7 +33,7 @@ class Distribution private constructor(
|
|||||||
/**
|
/**
|
||||||
* The path of the distribution fat JAR on disk, if available.
|
* The path of the distribution fat JAR on disk, if available.
|
||||||
*/
|
*/
|
||||||
file: File? = null,
|
file: Path? = null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The URL of the distribution fat JAR, if available.
|
* The URL of the distribution fat JAR, if available.
|
||||||
@ -47,43 +49,39 @@ class Distribution private constructor(
|
|||||||
/**
|
/**
|
||||||
* The path to the distribution fat JAR.
|
* The path to the distribution fat JAR.
|
||||||
*/
|
*/
|
||||||
val path: File = file ?: nodePrefix / "$version"
|
val path: Path = file ?: nodePrefix / version
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path to the distribution fat JAR.
|
* The path to the distribution fat JAR.
|
||||||
*/
|
*/
|
||||||
val cordaJar: File = path / "corda.jar"
|
val cordaJar: Path = path / "corda.jar"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path to available Cordapps for this distribution.
|
* The path to available Cordapps for this distribution.
|
||||||
*/
|
*/
|
||||||
val cordappDirectory: File = path / "apps"
|
val cordappDirectory: Path = path / "apps"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path to network bootstrapping tool.
|
* The path to network bootstrapping tool.
|
||||||
*/
|
*/
|
||||||
val networkBootstrapper: File = path / "network-bootstrapper.jar"
|
val networkBootstrapper: Path = path / "network-bootstrapper.jar"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that the distribution is available on disk.
|
* Ensure that the distribution is available on disk.
|
||||||
*/
|
*/
|
||||||
fun ensureAvailable() {
|
fun ensureAvailable() {
|
||||||
if (!cordaJar.exists()) {
|
if (cordaJar.exists()) return
|
||||||
if (url != null) {
|
val url = checkNotNull(url) { "File not found $cordaJar" }
|
||||||
try {
|
try {
|
||||||
FileUtils.forceMkdirParent(cordaJar)
|
cordaJar.parent.createDirectories()
|
||||||
FileUtils.copyURLToFile(url, cordaJar)
|
url.openStream().use { it.copyTo(cordaJar) }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
if (e.message!!.contains("HTTP response code: 401")) {
|
if ("HTTP response code: 401" in e.message!!) {
|
||||||
log.warn("CORDA_ARTIFACTORY_USERNAME ${System.getenv("CORDA_ARTIFACTORY_USERNAME")}")
|
log.warn("CORDA_ARTIFACTORY_USERNAME ${System.getenv("CORDA_ARTIFACTORY_USERNAME")}")
|
||||||
log.warn("CORDA_ARTIFACTORY_PASSWORD ${System.getenv("CORDA_ARTIFACTORY_PASSWORD")}")
|
log.warn("CORDA_ARTIFACTORY_PASSWORD ${System.getenv("CORDA_ARTIFACTORY_PASSWORD")}")
|
||||||
throw Exception("Incorrect Artifactory permission. Please set CORDA_ARTIFACTORY_USERNAME and CORDA_ARTIFACTORY_PASSWORD environment variables correctly.")
|
throw Exception("Incorrect Artifactory permission. Please set CORDA_ARTIFACTORY_USERNAME and CORDA_ARTIFACTORY_PASSWORD environment variables correctly.")
|
||||||
}
|
|
||||||
else throw Exception("Invalid Corda version $version", e)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw Exception("File not found $cordaJar")
|
|
||||||
}
|
}
|
||||||
|
throw e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +117,7 @@ class Distribution private constructor(
|
|||||||
* @param version The version of the Corda distribution.
|
* @param version The version of the Corda distribution.
|
||||||
* @param jarFile The path to the Corda fat JAR.
|
* @param jarFile The path to the Corda fat JAR.
|
||||||
*/
|
*/
|
||||||
fun fromJarFile(version: String, jarFile: File? = null): Distribution {
|
fun fromJarFile(version: String, jarFile: Path? = null): Distribution {
|
||||||
val distribution = Distribution(version, file = jarFile)
|
val distribution = Distribution(version, file = jarFile)
|
||||||
distributions.add(distribution)
|
distributions.add(distribution)
|
||||||
return distribution
|
return distribution
|
||||||
|
@ -14,7 +14,6 @@ import net.corda.behave.database.DatabaseConnection
|
|||||||
import net.corda.behave.database.DatabaseType
|
import net.corda.behave.database.DatabaseType
|
||||||
import net.corda.behave.file.LogSource
|
import net.corda.behave.file.LogSource
|
||||||
import net.corda.behave.file.currentDirectory
|
import net.corda.behave.file.currentDirectory
|
||||||
import net.corda.behave.file.div
|
|
||||||
import net.corda.behave.file.stagingRoot
|
import net.corda.behave.file.stagingRoot
|
||||||
import net.corda.behave.logging.getLogger
|
import net.corda.behave.logging.getLogger
|
||||||
import net.corda.behave.monitoring.PatternWatch
|
import net.corda.behave.monitoring.PatternWatch
|
||||||
@ -27,11 +26,13 @@ import net.corda.behave.ssh.MonitoringSSHClient
|
|||||||
import net.corda.behave.ssh.SSHClient
|
import net.corda.behave.ssh.SSHClient
|
||||||
import net.corda.client.rpc.CordaRPCClient
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.client.rpc.CordaRPCClientConfiguration
|
import net.corda.client.rpc.CordaRPCClientConfiguration
|
||||||
|
import net.corda.core.internal.div
|
||||||
|
import net.corda.core.internal.exists
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import org.apache.commons.io.FileUtils
|
import org.apache.commons.io.FileUtils
|
||||||
import java.io.File
|
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
|
import java.nio.file.Path
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
@ -40,7 +41,7 @@ import java.util.concurrent.CountDownLatch
|
|||||||
*/
|
*/
|
||||||
class Node(
|
class Node(
|
||||||
val config: Configuration,
|
val config: Configuration,
|
||||||
private val rootDirectory: File = currentDirectory,
|
private val rootDirectory: Path = currentDirectory,
|
||||||
private val settings: ServiceSettings = ServiceSettings()
|
private val settings: ServiceSettings = ServiceSettings()
|
||||||
) {
|
) {
|
||||||
|
|
||||||
@ -229,10 +230,10 @@ class Node(
|
|||||||
|
|
||||||
private fun installApps() {
|
private fun installApps() {
|
||||||
val version = config.distribution.version
|
val version = config.distribution.version
|
||||||
val appDirectory = stagingRoot / "deps/corda/$version/apps"
|
val appDirectory = stagingRoot / "deps" / "corda" / version / "apps"
|
||||||
if (appDirectory.exists()) {
|
if (appDirectory.exists()) {
|
||||||
val targetAppDirectory = runtimeDirectory / "cordapps"
|
val targetAppDirectory = runtimeDirectory / "cordapps"
|
||||||
FileUtils.copyDirectory(appDirectory, targetAppDirectory)
|
FileUtils.copyDirectory(appDirectory.toFile(), targetAppDirectory.toFile())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,7 +258,7 @@ class Node(
|
|||||||
|
|
||||||
private var includeFinance = false
|
private var includeFinance = false
|
||||||
|
|
||||||
private var directory: File? = null
|
private var directory: Path? = null
|
||||||
|
|
||||||
private var timeout = Duration.ofSeconds(60)
|
private var timeout = Duration.ofSeconds(60)
|
||||||
|
|
||||||
@ -307,7 +308,7 @@ class Node(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withDirectory(newDirectory: File): Builder {
|
fun withDirectory(newDirectory: Path): Builder {
|
||||||
directory = newDirectory
|
directory = newDirectory
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
@ -12,10 +12,10 @@ package net.corda.behave.node.configuration
|
|||||||
|
|
||||||
import net.corda.behave.database.DatabaseType
|
import net.corda.behave.database.DatabaseType
|
||||||
import net.corda.behave.logging.getLogger
|
import net.corda.behave.logging.getLogger
|
||||||
import net.corda.behave.node.*
|
import net.corda.behave.node.Distribution
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import org.apache.commons.io.FileUtils
|
import net.corda.core.internal.writeText
|
||||||
import java.io.File
|
import java.nio.file.Path
|
||||||
|
|
||||||
class Configuration(
|
class Configuration(
|
||||||
val name: String,
|
val name: String,
|
||||||
@ -53,8 +53,8 @@ class Configuration(
|
|||||||
private val extraConfig = (configElements.toList() + listOf(users, nodeInterface))
|
private val extraConfig = (configElements.toList() + listOf(users, nodeInterface))
|
||||||
.joinToString(separator = "\n") { it.generate(this) }
|
.joinToString(separator = "\n") { it.generate(this) }
|
||||||
|
|
||||||
fun writeToFile(file: File) {
|
fun writeToFile(file: Path) {
|
||||||
FileUtils.writeStringToFile(file, this.generate(), "UTF-8")
|
file.writeText(this.generate())
|
||||||
log.info(this.generate())
|
log.info(this.generate())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +64,7 @@ class Configuration(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val log = getLogger<Configuration>()
|
private val log = getLogger<Configuration>()
|
||||||
val DEFAULT_PASSWORD = "S0meS3cretW0rd"
|
const val DEFAULT_PASSWORD = "S0meS3cretW0rd"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -17,14 +17,14 @@ import net.corda.behave.process.output.OutputListener
|
|||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Subscriber
|
import rx.Subscriber
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.io.File
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import java.nio.file.Path
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
open class Command(
|
open class Command(
|
||||||
private val command: List<String>,
|
private val command: List<String>,
|
||||||
private val directory: File = currentDirectory,
|
private val directory: Path = currentDirectory,
|
||||||
private val timeout: Duration = 2.minutes
|
private val timeout: Duration = 2.minutes
|
||||||
): Closeable {
|
): Closeable {
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ open class Command(
|
|||||||
try {
|
try {
|
||||||
log.info("Command: $command")
|
log.info("Command: $command")
|
||||||
val processBuilder = ProcessBuilder(command)
|
val processBuilder = ProcessBuilder(command)
|
||||||
.directory(directory)
|
.directory(directory.toFile())
|
||||||
.redirectErrorStream(true)
|
.redirectErrorStream(true)
|
||||||
processBuilder.environment().putAll(System.getenv())
|
processBuilder.environment().putAll(System.getenv())
|
||||||
process = processBuilder.start()
|
process = processBuilder.start()
|
||||||
|
@ -11,12 +11,13 @@
|
|||||||
package net.corda.behave.process
|
package net.corda.behave.process
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.nio.file.Path
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
|
||||||
class JarCommand(
|
class JarCommand(
|
||||||
val jarFile: File,
|
jarFile: Path,
|
||||||
arguments: Array<String>,
|
arguments: Array<String>,
|
||||||
directory: File,
|
directory: Path,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
enableRemoteDebugging: Boolean = false
|
enableRemoteDebugging: Boolean = false
|
||||||
) : Command(
|
) : Command(
|
||||||
|
@ -10,11 +10,10 @@
|
|||||||
|
|
||||||
package net.corda.behave.scenarios.helpers
|
package net.corda.behave.scenarios.helpers
|
||||||
|
|
||||||
import net.corda.behave.file.div
|
|
||||||
import net.corda.behave.minutes
|
import net.corda.behave.minutes
|
||||||
import net.corda.behave.process.JarCommand
|
import net.corda.behave.process.JarCommand
|
||||||
import net.corda.behave.scenarios.ScenarioState
|
import net.corda.behave.scenarios.ScenarioState
|
||||||
import java.io.File
|
import net.corda.core.internal.div
|
||||||
|
|
||||||
class Startup(state: ScenarioState) : Substeps(state) {
|
class Startup(state: ScenarioState) : Substeps(state) {
|
||||||
|
|
||||||
@ -113,7 +112,7 @@ class Startup(state: ScenarioState) : Substeps(state) {
|
|||||||
// assumption is there is a Main() method declared in the manifest of the JAR
|
// assumption is there is a Main() method declared in the manifest of the JAR
|
||||||
// eg. Main-Class: net.corda.notaryhealthcheck.MainKt
|
// eg. Main-Class: net.corda.notaryhealthcheck.MainKt
|
||||||
val cordappDirectory = node(nodeName).config.distribution.cordappDirectory
|
val cordappDirectory = node(nodeName).config.distribution.cordappDirectory
|
||||||
val cordappJar : File = cordappDirectory / "$cordapp.jar"
|
val cordappJar = cordappDirectory / "$cordapp.jar"
|
||||||
// Execute
|
// Execute
|
||||||
val command = JarCommand(cordappJar, args as Array<String>, cordappDirectory, 1.minutes)
|
val command = JarCommand(cordappJar, args as Array<String>, cordappDirectory, 1.minutes)
|
||||||
command.start()
|
command.start()
|
||||||
|
@ -36,7 +36,6 @@ import net.corda.nodeapi.internal.serialization.SerializationFactoryImpl
|
|||||||
import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme
|
import net.corda.nodeapi.internal.serialization.amqp.AMQPServerSerializationScheme
|
||||||
import net.corda.nodeapi.internal.serialization.kryo.AbstractKryoSerializationScheme
|
import net.corda.nodeapi.internal.serialization.kryo.AbstractKryoSerializationScheme
|
||||||
import net.corda.nodeapi.internal.serialization.kryo.kryoMagic
|
import net.corda.nodeapi.internal.serialization.kryo.kryoMagic
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.nio.file.StandardCopyOption.REPLACE_EXISTING
|
import java.nio.file.StandardCopyOption.REPLACE_EXISTING
|
||||||
@ -115,13 +114,13 @@ class NetworkBootstrapper {
|
|||||||
val cordappsDir = (nodeDir / "cordapps").createDirectories()
|
val cordappsDir = (nodeDir / "cordapps").createDirectories()
|
||||||
cordappJars.forEach { it.copyToDirectory(cordappsDir) }
|
cordappJars.forEach { it.copyToDirectory(cordappsDir) }
|
||||||
}
|
}
|
||||||
Files.delete(cordaJar)
|
cordaJar.delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractCordaJarTo(directory: Path): Path {
|
private fun extractCordaJarTo(directory: Path): Path {
|
||||||
val cordaJarPath = directory / "corda.jar"
|
val cordaJarPath = directory / "corda.jar"
|
||||||
if (!cordaJarPath.exists()) {
|
if (!cordaJarPath.exists()) {
|
||||||
Thread.currentThread().contextClassLoader.getResourceAsStream("corda.jar").copyTo(cordaJarPath)
|
Thread.currentThread().contextClassLoader.getResourceAsStream("corda.jar").use { it.copyTo(cordaJarPath) }
|
||||||
}
|
}
|
||||||
return cordaJarPath
|
return cordaJarPath
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,7 @@
|
|||||||
package net.corda.nodeapi.internal.network
|
package net.corda.nodeapi.internal.network
|
||||||
|
|
||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
import net.corda.core.internal.ThreadBox
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.createDirectories
|
|
||||||
import net.corda.core.internal.isRegularFile
|
|
||||||
import net.corda.core.internal.list
|
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import rx.Scheduler
|
import rx.Scheduler
|
||||||
@ -25,7 +22,6 @@ import java.nio.file.Files
|
|||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.StandardCopyOption.COPY_ATTRIBUTES
|
import java.nio.file.StandardCopyOption.COPY_ATTRIBUTES
|
||||||
import java.nio.file.StandardCopyOption.REPLACE_EXISTING
|
import java.nio.file.StandardCopyOption.REPLACE_EXISTING
|
||||||
import java.nio.file.attribute.BasicFileAttributes
|
|
||||||
import java.nio.file.attribute.FileTime
|
import java.nio.file.attribute.FileTime
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@ -110,10 +106,10 @@ class NodeInfoFilesCopier(scheduler: Scheduler = Schedulers.io()) : AutoCloseabl
|
|||||||
private fun poll() {
|
private fun poll() {
|
||||||
nodeDataMapBox.locked {
|
nodeDataMapBox.locked {
|
||||||
for (nodeData in values) {
|
for (nodeData in values) {
|
||||||
nodeData.nodeDir.list { paths ->
|
nodeData.nodeDir.list { paths -> paths
|
||||||
paths.filter { it.isRegularFile() }
|
.filter { it.isRegularFile() }
|
||||||
.filter { it.fileName.toString().startsWith(NODE_INFO_FILE_NAME_PREFIX) }
|
.filter { it.fileName.toString().startsWith(NODE_INFO_FILE_NAME_PREFIX) }
|
||||||
.forEach { path -> processPath(nodeData, path) }
|
.forEach { processPath(nodeData, it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -123,7 +119,7 @@ class NodeInfoFilesCopier(scheduler: Scheduler = Schedulers.io()) : AutoCloseabl
|
|||||||
// be copied.
|
// be copied.
|
||||||
private fun processPath(nodeData: NodeData, path: Path) {
|
private fun processPath(nodeData: NodeData, path: Path) {
|
||||||
nodeDataMapBox.alreadyLocked {
|
nodeDataMapBox.alreadyLocked {
|
||||||
val newTimestamp = Files.readAttributes(path, BasicFileAttributes::class.java).lastModifiedTime()
|
val newTimestamp = path.lastModifiedTime()
|
||||||
val previousTimestamp = nodeData.previouslySeenFiles.put(path, newTimestamp) ?: FileTime.fromMillis(-1)
|
val previousTimestamp = nodeData.previouslySeenFiles.put(path, newTimestamp) ?: FileTime.fromMillis(-1)
|
||||||
if (newTimestamp > previousTimestamp) {
|
if (newTimestamp > previousTimestamp) {
|
||||||
for (destination in this.values.filter { it.nodeDir != nodeData.nodeDir }.map { it.additionalNodeInfoDirectory }) {
|
for (destination in this.values.filter { it.nodeDir != nodeData.nodeDir }.map { it.additionalNodeInfoDirectory }) {
|
||||||
@ -143,18 +139,18 @@ class NodeInfoFilesCopier(scheduler: Scheduler = Schedulers.io()) : AutoCloseabl
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// First copy the file to a temporary file within the appropriate directory.
|
// First copy the file to a temporary file within the appropriate directory.
|
||||||
Files.copy(source, tempDestination, COPY_ATTRIBUTES, REPLACE_EXISTING)
|
source.copyTo(tempDestination, COPY_ATTRIBUTES, REPLACE_EXISTING)
|
||||||
} catch (exception: IOException) {
|
} catch (exception: IOException) {
|
||||||
log.warn("Couldn't copy $source to $tempDestination.", exception)
|
log.warn("Couldn't copy $source to $tempDestination.", exception)
|
||||||
Files.delete(tempDestination)
|
tempDestination.delete()
|
||||||
throw exception
|
throw exception
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// Then rename it to the desired name. This way the file 'appears' on the filesystem as an atomic operation.
|
// Then rename it to the desired name. This way the file 'appears' on the filesystem as an atomic operation.
|
||||||
Files.move(tempDestination, destination, REPLACE_EXISTING)
|
tempDestination.moveTo(destination, REPLACE_EXISTING)
|
||||||
} catch (exception: IOException) {
|
} catch (exception: IOException) {
|
||||||
log.warn("Couldn't move $tempDestination to $destination.", exception)
|
log.warn("Couldn't move $tempDestination to $destination.", exception)
|
||||||
Files.delete(tempDestination)
|
tempDestination.delete()
|
||||||
throw exception
|
throw exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import com.esotericsoftware.kryo.io.Output
|
|||||||
import com.esotericsoftware.kryo.serializers.FieldSerializer
|
import com.esotericsoftware.kryo.serializers.FieldSerializer
|
||||||
import com.esotericsoftware.kryo.util.DefaultClassResolver
|
import com.esotericsoftware.kryo.util.DefaultClassResolver
|
||||||
import com.esotericsoftware.kryo.util.Util
|
import com.esotericsoftware.kryo.util.Util
|
||||||
|
import net.corda.core.internal.writer
|
||||||
import net.corda.core.serialization.ClassWhitelist
|
import net.corda.core.serialization.ClassWhitelist
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.serialization.SerializationContext
|
import net.corda.core.serialization.SerializationContext
|
||||||
@ -26,10 +27,9 @@ import net.corda.nodeapi.internal.serialization.kryo.ThrowableSerializer
|
|||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
import java.lang.reflect.Modifier.isAbstract
|
import java.lang.reflect.Modifier.isAbstract
|
||||||
import java.nio.charset.StandardCharsets
|
import java.nio.charset.StandardCharsets.UTF_8
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.nio.file.StandardOpenOption
|
import java.nio.file.StandardOpenOption.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -216,7 +216,7 @@ class LoggingWhitelist(val delegate: ClassWhitelist, val global: Boolean = true)
|
|||||||
val fileName = System.getenv("WHITELIST_FILE")
|
val fileName = System.getenv("WHITELIST_FILE")
|
||||||
if (fileName != null && fileName.isNotEmpty()) {
|
if (fileName != null && fileName.isNotEmpty()) {
|
||||||
try {
|
try {
|
||||||
return PrintWriter(Files.newBufferedWriter(Paths.get(fileName), StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.APPEND, StandardOpenOption.WRITE), true)
|
return PrintWriter(Paths.get(fileName).writer(UTF_8, CREATE, APPEND, WRITE), true)
|
||||||
} catch (ioEx: Exception) {
|
} catch (ioEx: Exception) {
|
||||||
log.error("Could not open/create whitelist journal file for append: $fileName", ioEx)
|
log.error("Could not open/create whitelist journal file for append: $fileName", ioEx)
|
||||||
}
|
}
|
||||||
|
@ -11,18 +11,20 @@
|
|||||||
package net.corda.nodeapi.internal.network
|
package net.corda.nodeapi.internal.network
|
||||||
|
|
||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
|
import net.corda.core.internal.div
|
||||||
|
import net.corda.core.internal.list
|
||||||
|
import net.corda.core.internal.write
|
||||||
import net.corda.nodeapi.eventually
|
import net.corda.nodeapi.eventually
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.rules.TemporaryFolder
|
import org.junit.rules.TemporaryFolder
|
||||||
import rx.schedulers.TestScheduler
|
import rx.schedulers.TestScheduler
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.streams.toList
|
import kotlin.streams.toList
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class NodeInfoFilesCopierTest {
|
class NodeInfoFilesCopierTest {
|
||||||
companion object {
|
companion object {
|
||||||
@ -31,9 +33,9 @@ class NodeInfoFilesCopierTest {
|
|||||||
private const val NODE_2_PATH = "node2"
|
private const val NODE_2_PATH = "node2"
|
||||||
|
|
||||||
private val content = "blah".toByteArray(Charsets.UTF_8)
|
private val content = "blah".toByteArray(Charsets.UTF_8)
|
||||||
private val GOOD_NODE_INFO_NAME = "${NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX}test"
|
private const val GOOD_NODE_INFO_NAME = "${NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX}test"
|
||||||
private val GOOD_NODE_INFO_NAME_2 = "${NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX}anotherNode"
|
private const val GOOD_NODE_INFO_NAME_2 = "${NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX}anotherNode"
|
||||||
private val BAD_NODE_INFO_NAME = "something"
|
private const val BAD_NODE_INFO_NAME = "something"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
@ -65,8 +67,8 @@ class NodeInfoFilesCopierTest {
|
|||||||
advanceTime()
|
advanceTime()
|
||||||
|
|
||||||
// Create 2 files, a nodeInfo and another file in node1 folder.
|
// Create 2 files, a nodeInfo and another file in node1 folder.
|
||||||
Files.write(node1RootPath.resolve(GOOD_NODE_INFO_NAME), content)
|
(node1RootPath / GOOD_NODE_INFO_NAME).write(content)
|
||||||
Files.write(node1RootPath.resolve(BAD_NODE_INFO_NAME), content)
|
(node1RootPath / BAD_NODE_INFO_NAME).write(content)
|
||||||
|
|
||||||
// Configure the second node.
|
// Configure the second node.
|
||||||
nodeInfoFilesCopier.addConfig(node2RootPath)
|
nodeInfoFilesCopier.addConfig(node2RootPath)
|
||||||
@ -86,8 +88,8 @@ class NodeInfoFilesCopierTest {
|
|||||||
advanceTime()
|
advanceTime()
|
||||||
|
|
||||||
// Create 2 files, one of which to be copied, in a node root path.
|
// Create 2 files, one of which to be copied, in a node root path.
|
||||||
Files.write(node2RootPath.resolve(GOOD_NODE_INFO_NAME), content)
|
(node2RootPath / GOOD_NODE_INFO_NAME).write(content)
|
||||||
Files.write(node2RootPath.resolve(BAD_NODE_INFO_NAME), content)
|
(node2RootPath / BAD_NODE_INFO_NAME).write(content)
|
||||||
advanceTime()
|
advanceTime()
|
||||||
|
|
||||||
eventually<AssertionError, Unit>(Duration.ofMinutes(1)) {
|
eventually<AssertionError, Unit>(Duration.ofMinutes(1)) {
|
||||||
@ -104,14 +106,14 @@ class NodeInfoFilesCopierTest {
|
|||||||
advanceTime()
|
advanceTime()
|
||||||
|
|
||||||
// Create a file, in node 2 root path.
|
// Create a file, in node 2 root path.
|
||||||
Files.write(node2RootPath.resolve(GOOD_NODE_INFO_NAME), content)
|
(node2RootPath / GOOD_NODE_INFO_NAME).write(content)
|
||||||
advanceTime()
|
advanceTime()
|
||||||
|
|
||||||
// Remove node 2
|
// Remove node 2
|
||||||
nodeInfoFilesCopier.removeConfig(node2RootPath)
|
nodeInfoFilesCopier.removeConfig(node2RootPath)
|
||||||
|
|
||||||
// Create another file in node 2 directory.
|
// Create another file in node 2 directory.
|
||||||
Files.write(node2RootPath.resolve(GOOD_NODE_INFO_NAME_2), content)
|
(node2RootPath / GOOD_NODE_INFO_NAME).write(content)
|
||||||
advanceTime()
|
advanceTime()
|
||||||
|
|
||||||
eventually<AssertionError, Unit>(Duration.ofMinutes(1)) {
|
eventually<AssertionError, Unit>(Duration.ofMinutes(1)) {
|
||||||
@ -130,11 +132,11 @@ class NodeInfoFilesCopierTest {
|
|||||||
nodeInfoFilesCopier.reset()
|
nodeInfoFilesCopier.reset()
|
||||||
|
|
||||||
advanceTime()
|
advanceTime()
|
||||||
Files.write(node2RootPath.resolve(GOOD_NODE_INFO_NAME_2), content)
|
(node2RootPath / GOOD_NODE_INFO_NAME_2).write(content)
|
||||||
|
|
||||||
// Give some time to the filesystem to report the change.
|
// Give some time to the filesystem to report the change.
|
||||||
Thread.sleep(100)
|
Thread.sleep(100)
|
||||||
assertEquals(0, Files.list(node1AdditionalNodeInfoPath).toList().size)
|
assertThat(node1AdditionalNodeInfoPath.list()).isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun advanceTime() {
|
private fun advanceTime() {
|
||||||
@ -142,8 +144,8 @@ class NodeInfoFilesCopierTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkDirectoryContainsSingleFile(path: Path, filename: String) {
|
private fun checkDirectoryContainsSingleFile(path: Path, filename: String) {
|
||||||
assertEquals(1, Files.list(path).toList().size)
|
val files = path.list()
|
||||||
val onlyFileName = Files.list(path).toList().first().fileName.toString()
|
assertThat(files).hasSize(1)
|
||||||
assertEquals(filename, onlyFileName)
|
assertThat(files[0].fileName.toString()).isEqualTo(filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,8 +14,8 @@ import net.corda.core.serialization.*
|
|||||||
import net.corda.testing.common.internal.ProjectStructure.projectRootDir
|
import net.corda.testing.common.internal.ProjectStructure.projectRootDir
|
||||||
import org.assertj.core.api.Assertions
|
import org.assertj.core.api.Assertions
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
|
||||||
import java.io.NotSerializableException
|
import java.io.NotSerializableException
|
||||||
|
import java.net.URI
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -23,11 +23,11 @@ import kotlin.test.assertTrue
|
|||||||
|
|
||||||
class EnumEvolvabilityTests {
|
class EnumEvolvabilityTests {
|
||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
var localPath = projectRootDir.toUri().resolve(
|
var localPath: URI = projectRootDir.toUri().resolve(
|
||||||
"node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp")
|
"node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp")
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val VERBOSE = false
|
const val VERBOSE = false
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class NotAnnotated {
|
enum class NotAnnotated {
|
||||||
@ -442,8 +442,7 @@ class EnumEvolvabilityTests {
|
|||||||
//File(URI("$localPath/$resource")).writeBytes(
|
//File(URI("$localPath/$resource")).writeBytes(
|
||||||
// SerializationOutput(sf).serialize(WrapsUnknown(WithUnknownTest.D)).bytes)
|
// SerializationOutput(sf).serialize(WrapsUnknown(WithUnknownTest.D)).bytes)
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val sb1 = EvolvabilityTests::class.java.getResource(resource).readBytes()
|
||||||
val sb1 = File(path.toURI()).readBytes()
|
|
||||||
|
|
||||||
val envelope = DeserializationInput(sf).deserializeAndReturnEnvelope(SerializedBytes<WrapsUnknown>(sb1)).envelope
|
val envelope = DeserializationInput(sf).deserializeAndReturnEnvelope(SerializedBytes<WrapsUnknown>(sb1)).envelope
|
||||||
|
|
||||||
|
@ -10,25 +10,25 @@
|
|||||||
|
|
||||||
package net.corda.nodeapi.internal.serialization.amqp
|
package net.corda.nodeapi.internal.serialization.amqp
|
||||||
|
|
||||||
import net.corda.core.internal.packageName
|
import net.corda.core.internal.toPath
|
||||||
import net.corda.core.serialization.CordaSerializationTransformEnumDefault
|
import net.corda.core.serialization.CordaSerializationTransformEnumDefault
|
||||||
import net.corda.core.serialization.CordaSerializationTransformEnumDefaults
|
import net.corda.core.serialization.CordaSerializationTransformEnumDefaults
|
||||||
import net.corda.core.serialization.SerializedBytes
|
import net.corda.core.serialization.SerializedBytes
|
||||||
import net.corda.testing.common.internal.ProjectStructure.projectRootDir
|
import net.corda.testing.common.internal.ProjectStructure.projectRootDir
|
||||||
import org.assertj.core.api.Assertions
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
|
||||||
import java.io.NotSerializableException
|
import java.io.NotSerializableException
|
||||||
|
import java.net.URI
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNotNull
|
import kotlin.test.assertNotNull
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
// NOTE: To recreate the test files used by these tests uncomment the original test classes and comment
|
// NOTE: To recreate the test files used by these tests uncomment the original test classes and comment
|
||||||
// the new ones out, then change each test to write out the serialized bytes rather than read
|
// the new ones out, then change each test to write out the serialized bytes rather than read
|
||||||
// the file.
|
// the file.
|
||||||
class EnumEvolveTests {
|
class EnumEvolveTests {
|
||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
var localPath = projectRootDir.toUri().resolve(
|
var localPath: URI = projectRootDir.toUri().resolve(
|
||||||
"node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp")
|
"node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp")
|
||||||
|
|
||||||
// Version of the class as it was serialised
|
// Version of the class as it was serialised
|
||||||
@ -50,9 +50,9 @@ class EnumEvolveTests {
|
|||||||
// File(URI("$localPath/$resource")).writeBytes(
|
// File(URI("$localPath/$resource")).writeBytes(
|
||||||
// SerializationOutput(sf).serialize(C(DeserializeNewerSetToUnknown.D)).bytes)
|
// SerializationOutput(sf).serialize(C(DeserializeNewerSetToUnknown.D)).bytes)
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
|
|
||||||
val obj = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path.toURI()).readBytes()))
|
val obj = DeserializationInput(sf).deserialize(SerializedBytes<C>(url.readBytes()))
|
||||||
|
|
||||||
assertEquals(DeserializeNewerSetToUnknown.C, obj.e)
|
assertEquals(DeserializeNewerSetToUnknown.C, obj.e)
|
||||||
}
|
}
|
||||||
@ -80,17 +80,17 @@ class EnumEvolveTests {
|
|||||||
// File(URI("$localPath/$resource.D")).writeBytes(so.serialize(C(DeserializeNewerSetToUnknown2.D)).bytes)
|
// File(URI("$localPath/$resource.D")).writeBytes(so.serialize(C(DeserializeNewerSetToUnknown2.D)).bytes)
|
||||||
// File(URI("$localPath/$resource.E")).writeBytes(so.serialize(C(DeserializeNewerSetToUnknown2.E)).bytes)
|
// File(URI("$localPath/$resource.E")).writeBytes(so.serialize(C(DeserializeNewerSetToUnknown2.E)).bytes)
|
||||||
|
|
||||||
val path1 = EvolvabilityTests::class.java.getResource("$resource.C")
|
val url1 = EvolvabilityTests::class.java.getResource("$resource.C")
|
||||||
val path2 = EvolvabilityTests::class.java.getResource("$resource.D")
|
val url2 = EvolvabilityTests::class.java.getResource("$resource.D")
|
||||||
val path3 = EvolvabilityTests::class.java.getResource("$resource.E")
|
val url3 = EvolvabilityTests::class.java.getResource("$resource.E")
|
||||||
|
|
||||||
// C will just work
|
// C will just work
|
||||||
val obj1 = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path1.toURI()).readBytes()))
|
val obj1 = DeserializationInput(sf).deserialize(SerializedBytes<C>(url1.readBytes()))
|
||||||
// D will transform directly to C
|
// D will transform directly to C
|
||||||
val obj2 = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path2.toURI()).readBytes()))
|
val obj2 = DeserializationInput(sf).deserialize(SerializedBytes<C>(url2.readBytes()))
|
||||||
// E will have to transform from E -> D -> C to work, so this should exercise that part
|
// E will have to transform from E -> D -> C to work, so this should exercise that part
|
||||||
// of the evolution code
|
// of the evolution code
|
||||||
val obj3 = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path3.toURI()).readBytes()))
|
val obj3 = DeserializationInput(sf).deserialize(SerializedBytes<C>(url3.readBytes()))
|
||||||
|
|
||||||
assertEquals(DeserializeNewerSetToUnknown2.C, obj1.e)
|
assertEquals(DeserializeNewerSetToUnknown2.C, obj1.e)
|
||||||
assertEquals(DeserializeNewerSetToUnknown2.C, obj2.e)
|
assertEquals(DeserializeNewerSetToUnknown2.C, obj2.e)
|
||||||
@ -118,10 +118,10 @@ class EnumEvolveTests {
|
|||||||
// val so = SerializationOutput(sf)
|
// val so = SerializationOutput(sf)
|
||||||
// File(URI("$localPath/$resource")).writeBytes(so.serialize(C(DeserializeNewerWithNoRule.D)).bytes)
|
// File(URI("$localPath/$resource")).writeBytes(so.serialize(C(DeserializeNewerWithNoRule.D)).bytes)
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
|
|
||||||
Assertions.assertThatThrownBy {
|
assertThatThrownBy {
|
||||||
DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path.toURI()).readBytes()))
|
DeserializationInput(sf).deserialize(SerializedBytes<C>(url.readBytes()))
|
||||||
}.isInstanceOf(NotSerializableException::class.java)
|
}.isInstanceOf(NotSerializableException::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,9 +184,9 @@ class EnumEvolveTests {
|
|||||||
val path1_B = EvolvabilityTests::class.java.getResource("$resource.1.B")
|
val path1_B = EvolvabilityTests::class.java.getResource("$resource.1.B")
|
||||||
val path1_C = EvolvabilityTests::class.java.getResource("$resource.1.C")
|
val path1_C = EvolvabilityTests::class.java.getResource("$resource.1.C")
|
||||||
|
|
||||||
val obj1_AA = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path1_AA.toURI()).readBytes()))
|
val obj1_AA = DeserializationInput(sf).deserialize(SerializedBytes<C>(path1_AA.readBytes()))
|
||||||
val obj1_B = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path1_B.toURI()).readBytes()))
|
val obj1_B = DeserializationInput(sf).deserialize(SerializedBytes<C>(path1_B.readBytes()))
|
||||||
val obj1_C = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path1_C.toURI()).readBytes()))
|
val obj1_C = DeserializationInput(sf).deserialize(SerializedBytes<C>(path1_C.readBytes()))
|
||||||
|
|
||||||
assertEquals(DeserializeWithRename.A, obj1_AA.e)
|
assertEquals(DeserializeWithRename.A, obj1_AA.e)
|
||||||
assertEquals(DeserializeWithRename.B, obj1_B.e)
|
assertEquals(DeserializeWithRename.B, obj1_B.e)
|
||||||
@ -199,9 +199,9 @@ class EnumEvolveTests {
|
|||||||
val path2_BB = EvolvabilityTests::class.java.getResource("$resource.2.BB")
|
val path2_BB = EvolvabilityTests::class.java.getResource("$resource.2.BB")
|
||||||
val path2_C = EvolvabilityTests::class.java.getResource("$resource.2.C")
|
val path2_C = EvolvabilityTests::class.java.getResource("$resource.2.C")
|
||||||
|
|
||||||
val obj2_AA = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path2_AA.toURI()).readBytes()))
|
val obj2_AA = DeserializationInput(sf).deserialize(SerializedBytes<C>(path2_AA.readBytes()))
|
||||||
val obj2_BB = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path2_BB.toURI()).readBytes()))
|
val obj2_BB = DeserializationInput(sf).deserialize(SerializedBytes<C>(path2_BB.readBytes()))
|
||||||
val obj2_C = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path2_C.toURI()).readBytes()))
|
val obj2_C = DeserializationInput(sf).deserialize(SerializedBytes<C>(path2_C.readBytes()))
|
||||||
|
|
||||||
assertEquals(DeserializeWithRename.A, obj2_AA.e)
|
assertEquals(DeserializeWithRename.A, obj2_AA.e)
|
||||||
assertEquals(DeserializeWithRename.B, obj2_BB.e)
|
assertEquals(DeserializeWithRename.B, obj2_BB.e)
|
||||||
@ -214,9 +214,9 @@ class EnumEvolveTests {
|
|||||||
val path3_XX = EvolvabilityTests::class.java.getResource("$resource.3.XX")
|
val path3_XX = EvolvabilityTests::class.java.getResource("$resource.3.XX")
|
||||||
val path3_C = EvolvabilityTests::class.java.getResource("$resource.3.C")
|
val path3_C = EvolvabilityTests::class.java.getResource("$resource.3.C")
|
||||||
|
|
||||||
val obj3_AA = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path3_AA.toURI()).readBytes()))
|
val obj3_AA = DeserializationInput(sf).deserialize(SerializedBytes<C>(path3_AA.readBytes()))
|
||||||
val obj3_XX = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path3_XX.toURI()).readBytes()))
|
val obj3_XX = DeserializationInput(sf).deserialize(SerializedBytes<C>(path3_XX.readBytes()))
|
||||||
val obj3_C = DeserializationInput(sf).deserialize(SerializedBytes<C>(File(path3_C.toURI()).readBytes()))
|
val obj3_C = DeserializationInput(sf).deserialize(SerializedBytes<C>(path3_C.readBytes()))
|
||||||
|
|
||||||
assertEquals(DeserializeWithRename.A, obj3_AA.e)
|
assertEquals(DeserializeWithRename.A, obj3_AA.e)
|
||||||
assertEquals(DeserializeWithRename.B, obj3_XX.e)
|
assertEquals(DeserializeWithRename.B, obj3_XX.e)
|
||||||
@ -359,11 +359,11 @@ class EnumEvolveTests {
|
|||||||
Pair("$resource.5.G", MultiOperations.C))
|
Pair("$resource.5.G", MultiOperations.C))
|
||||||
|
|
||||||
fun load(l: List<Pair<String, MultiOperations>>) = l.map {
|
fun load(l: List<Pair<String, MultiOperations>>) = l.map {
|
||||||
assertNotNull (EvolvabilityTests::class.java.getResource(it.first))
|
assertNotNull(EvolvabilityTests::class.java.getResource(it.first))
|
||||||
assertTrue (File(EvolvabilityTests::class.java.getResource(it.first).toURI()).exists())
|
assertThat(EvolvabilityTests::class.java.getResource(it.first).toPath()).exists()
|
||||||
|
|
||||||
Pair(DeserializationInput(sf).deserialize(SerializedBytes<C>(
|
Pair(DeserializationInput(sf).deserialize(SerializedBytes<C>(
|
||||||
File(EvolvabilityTests::class.java.getResource(it.first).toURI()).readBytes())), it.second)
|
EvolvabilityTests::class.java.getResource(it.first).readBytes())), it.second)
|
||||||
}
|
}
|
||||||
|
|
||||||
load(stage1Resources).forEach { assertEquals(it.second, it.first.e) }
|
load(stage1Resources).forEach { assertEquals(it.second, it.first.e) }
|
||||||
@ -382,7 +382,7 @@ class EnumEvolveTests {
|
|||||||
|
|
||||||
data class C(val e: BadNewValue)
|
data class C(val e: BadNewValue)
|
||||||
|
|
||||||
Assertions.assertThatThrownBy {
|
assertThatThrownBy {
|
||||||
SerializationOutput(sf).serialize(C(BadNewValue.A))
|
SerializationOutput(sf).serialize(C(BadNewValue.A))
|
||||||
}.isInstanceOf(NotSerializableException::class.java)
|
}.isInstanceOf(NotSerializableException::class.java)
|
||||||
}
|
}
|
||||||
@ -399,7 +399,7 @@ class EnumEvolveTests {
|
|||||||
|
|
||||||
data class C(val e: OutOfOrder)
|
data class C(val e: OutOfOrder)
|
||||||
|
|
||||||
Assertions.assertThatThrownBy {
|
assertThatThrownBy {
|
||||||
SerializationOutput(sf).serialize(C(OutOfOrder.A))
|
SerializationOutput(sf).serialize(C(OutOfOrder.A))
|
||||||
}.isInstanceOf(NotSerializableException::class.java)
|
}.isInstanceOf(NotSerializableException::class.java)
|
||||||
}
|
}
|
||||||
@ -423,9 +423,9 @@ class EnumEvolveTests {
|
|||||||
// File(URI("$localPath/$resource")).writeBytes(
|
// File(URI("$localPath/$resource")).writeBytes(
|
||||||
// SerializationOutput(sf).serialize(C(ChangedOrdinality.A)).bytes)
|
// SerializationOutput(sf).serialize(C(ChangedOrdinality.A)).bytes)
|
||||||
|
|
||||||
Assertions.assertThatThrownBy {
|
assertThatThrownBy {
|
||||||
DeserializationInput(sf).deserialize(SerializedBytes<C>(
|
DeserializationInput(sf).deserialize(SerializedBytes<C>(
|
||||||
File(EvolvabilityTests::class.java.getResource(resource).toURI()).readBytes()))
|
EvolvabilityTests::class.java.getResource(resource).readBytes()))
|
||||||
}.isInstanceOf(NotSerializableException::class.java)
|
}.isInstanceOf(NotSerializableException::class.java)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
import net.corda.core.serialization.SerializedBytes
|
import net.corda.core.serialization.SerializedBytes
|
||||||
import org.assertj.core.api.Assertions
|
import org.assertj.core.api.Assertions
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
|
||||||
import java.io.NotSerializableException
|
import java.io.NotSerializableException
|
||||||
import java.time.DayOfWeek
|
import java.time.DayOfWeek
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -161,8 +160,7 @@ class EnumTests {
|
|||||||
|
|
||||||
@Test(expected = NotSerializableException::class)
|
@Test(expected = NotSerializableException::class)
|
||||||
fun changedEnum1() {
|
fun changedEnum1() {
|
||||||
val path = EnumTests::class.java.getResource("EnumTests.changedEnum1")
|
val url = EnumTests::class.java.getResource("EnumTests.changedEnum1")
|
||||||
val f = File(path.toURI())
|
|
||||||
|
|
||||||
data class C(val a: OldBras)
|
data class C(val a: OldBras)
|
||||||
|
|
||||||
@ -173,7 +171,7 @@ class EnumTests {
|
|||||||
// f.writeBytes(sc.bytes)
|
// f.writeBytes(sc.bytes)
|
||||||
// println(path)
|
// println(path)
|
||||||
|
|
||||||
val sc2 = f.readBytes()
|
val sc2 = url.readBytes()
|
||||||
|
|
||||||
// we expect this to throw
|
// we expect this to throw
|
||||||
DeserializationInput(sf1).deserialize(SerializedBytes<C>(sc2))
|
DeserializationInput(sf1).deserialize(SerializedBytes<C>(sc2))
|
||||||
@ -181,8 +179,7 @@ class EnumTests {
|
|||||||
|
|
||||||
@Test(expected = NotSerializableException::class)
|
@Test(expected = NotSerializableException::class)
|
||||||
fun changedEnum2() {
|
fun changedEnum2() {
|
||||||
val path = EnumTests::class.java.getResource("EnumTests.changedEnum2")
|
val url = EnumTests::class.java.getResource("EnumTests.changedEnum2")
|
||||||
val f = File(path.toURI())
|
|
||||||
|
|
||||||
data class C(val a: OldBras2)
|
data class C(val a: OldBras2)
|
||||||
|
|
||||||
@ -196,7 +193,7 @@ class EnumTests {
|
|||||||
// f.writeBytes(sc.bytes)
|
// f.writeBytes(sc.bytes)
|
||||||
// println(path)
|
// println(path)
|
||||||
|
|
||||||
val sc2 = f.readBytes()
|
val sc2 = url.readBytes()
|
||||||
|
|
||||||
// we expect this to throw
|
// we expect this to throw
|
||||||
DeserializationInput(sf1).deserialize(SerializedBytes<C>(sc2))
|
DeserializationInput(sf1).deserialize(SerializedBytes<C>(sc2))
|
||||||
|
@ -40,7 +40,7 @@ import kotlin.test.assertEquals
|
|||||||
class EvolvabilityTests {
|
class EvolvabilityTests {
|
||||||
// When regenerating the test files this needs to be set to the file system location of the resource files
|
// When regenerating the test files this needs to be set to the file system location of the resource files
|
||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
var localPath = projectRootDir.toUri().resolve(
|
var localPath: URI = projectRootDir.toUri().resolve(
|
||||||
"node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp")
|
"node-api/src/test/resources/net/corda/nodeapi/internal/serialization/amqp")
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -59,10 +59,8 @@ class EvolvabilityTests {
|
|||||||
// new version of the class, in this case the order of the parameters has been swapped
|
// new version of the class, in this case the order of the parameters has been swapped
|
||||||
data class C(val b: Int, val a: Int)
|
data class C(val b: Int, val a: Int)
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
val f = File(path.toURI())
|
val sc2 = url.readBytes()
|
||||||
|
|
||||||
val sc2 = f.readBytes()
|
|
||||||
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<C>(sc2))
|
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<C>(sc2))
|
||||||
|
|
||||||
assertEquals(A, deserializedC.a)
|
assertEquals(A, deserializedC.a)
|
||||||
@ -84,9 +82,8 @@ class EvolvabilityTests {
|
|||||||
// new version of the class, in this case the order of the parameters has been swapped
|
// new version of the class, in this case the order of the parameters has been swapped
|
||||||
data class C(val b: String, val a: Int)
|
data class C(val b: String, val a: Int)
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
val f = File(path.toURI())
|
val sc2 = url.readBytes()
|
||||||
val sc2 = f.readBytes()
|
|
||||||
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<C>(sc2))
|
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<C>(sc2))
|
||||||
|
|
||||||
assertEquals(A, deserializedC.a)
|
assertEquals(A, deserializedC.a)
|
||||||
@ -105,9 +102,8 @@ class EvolvabilityTests {
|
|||||||
|
|
||||||
data class C(val a: Int, val b: Int?)
|
data class C(val a: Int, val b: Int?)
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
val f = File(path.toURI())
|
val sc2 = url.readBytes()
|
||||||
val sc2 = f.readBytes()
|
|
||||||
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<C>(sc2))
|
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<C>(sc2))
|
||||||
|
|
||||||
assertEquals(A, deserializedC.a)
|
assertEquals(A, deserializedC.a)
|
||||||
@ -117,8 +113,7 @@ class EvolvabilityTests {
|
|||||||
@Test(expected = NotSerializableException::class)
|
@Test(expected = NotSerializableException::class)
|
||||||
fun addAdditionalParam() {
|
fun addAdditionalParam() {
|
||||||
val sf = testDefaultFactory()
|
val sf = testDefaultFactory()
|
||||||
val path = EvolvabilityTests::class.java.getResource("EvolvabilityTests.addAdditionalParam")
|
val url = EvolvabilityTests::class.java.getResource("EvolvabilityTests.addAdditionalParam")
|
||||||
val f = File(path.toURI())
|
|
||||||
@Suppress("UNUSED_VARIABLE")
|
@Suppress("UNUSED_VARIABLE")
|
||||||
val A = 1
|
val A = 1
|
||||||
|
|
||||||
@ -132,7 +127,7 @@ class EvolvabilityTests {
|
|||||||
// new version of the class, in this case a new parameter has been added (b)
|
// new version of the class, in this case a new parameter has been added (b)
|
||||||
data class C(val a: Int, val b: Int)
|
data class C(val a: Int, val b: Int)
|
||||||
|
|
||||||
val sc2 = f.readBytes()
|
val sc2 = url.readBytes()
|
||||||
|
|
||||||
// Expected to throw as we can't construct the new type as it contains a newly
|
// Expected to throw as we can't construct the new type as it contains a newly
|
||||||
// added parameter that isn't optional, i.e. not nullable and there isn't
|
// added parameter that isn't optional, i.e. not nullable and there isn't
|
||||||
@ -156,9 +151,8 @@ class EvolvabilityTests {
|
|||||||
|
|
||||||
data class CC(val b: String, val d: Int)
|
data class CC(val b: String, val d: Int)
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource("EvolvabilityTests.removeParameters")
|
val url = EvolvabilityTests::class.java.getResource("EvolvabilityTests.removeParameters")
|
||||||
val f = File(path.toURI())
|
val sc2 = url.readBytes()
|
||||||
val sc2 = f.readBytes()
|
|
||||||
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
||||||
|
|
||||||
assertEquals(B, deserializedCC.b)
|
assertEquals(B, deserializedCC.b)
|
||||||
@ -183,9 +177,8 @@ class EvolvabilityTests {
|
|||||||
|
|
||||||
data class CC(val a: Int, val e: Boolean?, val d: Int)
|
data class CC(val a: Int, val e: Boolean?, val d: Int)
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
val f = File(path.toURI())
|
val sc2 = url.readBytes()
|
||||||
val sc2 = f.readBytes()
|
|
||||||
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
||||||
|
|
||||||
assertEquals(A, deserializedCC.a)
|
assertEquals(A, deserializedCC.a)
|
||||||
@ -209,9 +202,8 @@ class EvolvabilityTests {
|
|||||||
constructor (a: Int) : this(a, "hello")
|
constructor (a: Int) : this(a, "hello")
|
||||||
}
|
}
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
val f = File(path.toURI())
|
val sc2 = url.readBytes()
|
||||||
val sc2 = f.readBytes()
|
|
||||||
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
||||||
|
|
||||||
assertEquals(A, deserializedCC.a)
|
assertEquals(A, deserializedCC.a)
|
||||||
@ -222,9 +214,8 @@ class EvolvabilityTests {
|
|||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
fun addMandatoryFieldWithAltConstructorUnAnnotated() {
|
fun addMandatoryFieldWithAltConstructorUnAnnotated() {
|
||||||
val sf = testDefaultFactory()
|
val sf = testDefaultFactory()
|
||||||
val path = EvolvabilityTests::class.java.getResource(
|
val url = EvolvabilityTests::class.java.getResource(
|
||||||
"EvolvabilityTests.addMandatoryFieldWithAltConstructorUnAnnotated")
|
"EvolvabilityTests.addMandatoryFieldWithAltConstructorUnAnnotated")
|
||||||
val f = File(path.toURI())
|
|
||||||
@Suppress("UNUSED_VARIABLE")
|
@Suppress("UNUSED_VARIABLE")
|
||||||
val A = 1
|
val A = 1
|
||||||
|
|
||||||
@ -242,7 +233,7 @@ class EvolvabilityTests {
|
|||||||
|
|
||||||
// we expect this to throw as we should not find any constructors
|
// we expect this to throw as we should not find any constructors
|
||||||
// capable of dealing with this
|
// capable of dealing with this
|
||||||
DeserializationInput(sf).deserialize(SerializedBytes<CC>(f.readBytes()))
|
DeserializationInput(sf).deserialize(SerializedBytes<CC>(url.readBytes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -265,9 +256,8 @@ class EvolvabilityTests {
|
|||||||
constructor (c: String, a: Int, b: Int) : this(a, b, c, "wibble")
|
constructor (c: String, a: Int, b: Int) : this(a, b, c, "wibble")
|
||||||
}
|
}
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
val f = File(path.toURI())
|
val sc2 = url.readBytes()
|
||||||
val sc2 = f.readBytes()
|
|
||||||
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
||||||
|
|
||||||
assertEquals(A, deserializedCC.a)
|
assertEquals(A, deserializedCC.a)
|
||||||
@ -298,9 +288,8 @@ class EvolvabilityTests {
|
|||||||
constructor (c: String, a: Int) : this(a, c, "wibble")
|
constructor (c: String, a: Int) : this(a, c, "wibble")
|
||||||
}
|
}
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
val f = File(path.toURI())
|
val sc2 = url.readBytes()
|
||||||
val sc2 = f.readBytes()
|
|
||||||
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
val deserializedCC = DeserializationInput(sf).deserialize(SerializedBytes<CC>(sc2))
|
||||||
|
|
||||||
assertEquals(A, deserializedCC.a)
|
assertEquals(A, deserializedCC.a)
|
||||||
@ -345,11 +334,11 @@ class EvolvabilityTests {
|
|||||||
constructor (a: Int, b: Int, c: Int, d: Int) : this(-1, c, b, a, d)
|
constructor (a: Int, b: Int, c: Int, d: Int) : this(-1, c, b, a, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
val path1 = EvolvabilityTests::class.java.getResource(resource1)
|
val url1 = EvolvabilityTests::class.java.getResource(resource1)
|
||||||
val path2 = EvolvabilityTests::class.java.getResource(resource2)
|
val url2 = EvolvabilityTests::class.java.getResource(resource2)
|
||||||
val path3 = EvolvabilityTests::class.java.getResource(resource3)
|
val url3 = EvolvabilityTests::class.java.getResource(resource3)
|
||||||
|
|
||||||
val sb1 = File(path1.toURI()).readBytes()
|
val sb1 = url1.readBytes()
|
||||||
val db1 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb1))
|
val db1 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb1))
|
||||||
|
|
||||||
assertEquals(a, db1.a)
|
assertEquals(a, db1.a)
|
||||||
@ -358,7 +347,7 @@ class EvolvabilityTests {
|
|||||||
assertEquals(-1, db1.d)
|
assertEquals(-1, db1.d)
|
||||||
assertEquals(-1, db1.e)
|
assertEquals(-1, db1.e)
|
||||||
|
|
||||||
val sb2 = File(path2.toURI()).readBytes()
|
val sb2 = url2.readBytes()
|
||||||
val db2 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb2))
|
val db2 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb2))
|
||||||
|
|
||||||
assertEquals(a, db2.a)
|
assertEquals(a, db2.a)
|
||||||
@ -367,7 +356,7 @@ class EvolvabilityTests {
|
|||||||
assertEquals(-1, db2.d)
|
assertEquals(-1, db2.d)
|
||||||
assertEquals(-1, db2.e)
|
assertEquals(-1, db2.e)
|
||||||
|
|
||||||
val sb3 = File(path3.toURI()).readBytes()
|
val sb3 = url3.readBytes()
|
||||||
val db3 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb3))
|
val db3 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb3))
|
||||||
|
|
||||||
assertEquals(a, db3.a)
|
assertEquals(a, db3.a)
|
||||||
@ -394,9 +383,8 @@ class EvolvabilityTests {
|
|||||||
|
|
||||||
data class Outer(val a: Int, val b: Inner)
|
data class Outer(val a: Int, val b: Inner)
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
val f = File(path.toURI())
|
val sc2 = url.readBytes()
|
||||||
val sc2 = f.readBytes()
|
|
||||||
val outer = DeserializationInput(sf).deserialize(SerializedBytes<Outer>(sc2))
|
val outer = DeserializationInput(sf).deserialize(SerializedBytes<Outer>(sc2))
|
||||||
|
|
||||||
assertEquals(oa, outer.a)
|
assertEquals(oa, outer.a)
|
||||||
@ -449,11 +437,11 @@ class EvolvabilityTests {
|
|||||||
constructor (b: Int, c: Int, d: Int, e: Int, f: Int) : this(b, c, d, e, f, -1)
|
constructor (b: Int, c: Int, d: Int, e: Int, f: Int) : this(b, c, d, e, f, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
val path1 = EvolvabilityTests::class.java.getResource(resource1)
|
val url1 = EvolvabilityTests::class.java.getResource(resource1)
|
||||||
val path2 = EvolvabilityTests::class.java.getResource(resource2)
|
val url2 = EvolvabilityTests::class.java.getResource(resource2)
|
||||||
val path3 = EvolvabilityTests::class.java.getResource(resource3)
|
val url3 = EvolvabilityTests::class.java.getResource(resource3)
|
||||||
|
|
||||||
val sb1 = File(path1.toURI()).readBytes()
|
val sb1 = url1.readBytes()
|
||||||
val db1 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb1))
|
val db1 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb1))
|
||||||
|
|
||||||
assertEquals(b, db1.b)
|
assertEquals(b, db1.b)
|
||||||
@ -463,7 +451,7 @@ class EvolvabilityTests {
|
|||||||
assertEquals(-1, db1.f)
|
assertEquals(-1, db1.f)
|
||||||
assertEquals(-1, db1.g)
|
assertEquals(-1, db1.g)
|
||||||
|
|
||||||
val sb2 = File(path2.toURI()).readBytes()
|
val sb2 = url2.readBytes()
|
||||||
val db2 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb2))
|
val db2 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb2))
|
||||||
|
|
||||||
assertEquals(b, db2.b)
|
assertEquals(b, db2.b)
|
||||||
@ -473,7 +461,7 @@ class EvolvabilityTests {
|
|||||||
assertEquals(-1, db2.f)
|
assertEquals(-1, db2.f)
|
||||||
assertEquals(-1, db1.g)
|
assertEquals(-1, db1.g)
|
||||||
|
|
||||||
val sb3 = File(path3.toURI()).readBytes()
|
val sb3 = url3.readBytes()
|
||||||
val db3 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb3))
|
val db3 = DeserializationInput(sf).deserialize(SerializedBytes<C>(sb3))
|
||||||
|
|
||||||
assertEquals(b, db3.b)
|
assertEquals(b, db3.b)
|
||||||
@ -511,9 +499,8 @@ class EvolvabilityTests {
|
|||||||
//
|
//
|
||||||
val resource = "networkParams.r3corda.6a6b6f256"
|
val resource = "networkParams.r3corda.6a6b6f256"
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
val f = File(path.toURI())
|
val sc2 = url.readBytes()
|
||||||
val sc2 = f.readBytes()
|
|
||||||
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<SignedData<NetworkParameters>>(sc2))
|
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<SignedData<NetworkParameters>>(sc2))
|
||||||
val networkParams = DeserializationInput(sf).deserialize(deserializedC.raw)
|
val networkParams = DeserializationInput(sf).deserialize(deserializedC.raw)
|
||||||
|
|
||||||
@ -548,7 +535,7 @@ class EvolvabilityTests {
|
|||||||
val signed = SignedData(serialized, sig)
|
val signed = SignedData(serialized, sig)
|
||||||
val signedAndSerialized = testOutput.serialize(signed)
|
val signedAndSerialized = testOutput.serialize(signed)
|
||||||
|
|
||||||
File(URI("$localPath/$resource")).writeBytes( signedAndSerialized.bytes)
|
File(URI("$localPath/$resource")).writeBytes(signedAndSerialized.bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@ -581,10 +568,9 @@ class EvolvabilityTests {
|
|||||||
constructor() : this(0, 0, 0, 0)
|
constructor() : this(0, 0, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource(resource)
|
val url = EvolvabilityTests::class.java.getResource(resource)
|
||||||
val f = File(path.toURI())
|
|
||||||
|
|
||||||
val sc2 = f.readBytes()
|
val sc2 = url.readBytes()
|
||||||
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<C>(sc2))
|
val deserializedC = DeserializationInput(sf).deserialize(SerializedBytes<C>(sc2))
|
||||||
|
|
||||||
assertEquals(1, deserializedC.a)
|
assertEquals(1, deserializedC.a)
|
||||||
|
@ -277,7 +277,7 @@ class GenericsTests {
|
|||||||
|
|
||||||
assertEquals("wibble",
|
assertEquals("wibble",
|
||||||
DeserializationInput(sf).deserialize(SerializedBytes<ForceWildcard<*>>(
|
DeserializationInput(sf).deserialize(SerializedBytes<ForceWildcard<*>>(
|
||||||
File(GenericsTests::class.java.getResource(resource).toURI()).readBytes())).t)
|
GenericsTests::class.java.getResource(resource).readBytes())).t)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class StateAndString(val state: TransactionState<*>, val ref: String)
|
data class StateAndString(val state: TransactionState<*>, val ref: String)
|
||||||
|
@ -14,9 +14,8 @@ import net.corda.core.serialization.ClassWhitelist
|
|||||||
import net.corda.core.serialization.SerializedBytes
|
import net.corda.core.serialization.SerializedBytes
|
||||||
import net.corda.nodeapi.internal.serialization.AllWhitelist
|
import net.corda.nodeapi.internal.serialization.AllWhitelist
|
||||||
import net.corda.nodeapi.internal.serialization.carpenter.ClassCarpenter
|
import net.corda.nodeapi.internal.serialization.carpenter.ClassCarpenter
|
||||||
import org.assertj.core.api.Assertions
|
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
|
||||||
import java.io.NotSerializableException
|
import java.io.NotSerializableException
|
||||||
import java.lang.reflect.Type
|
import java.lang.reflect.Type
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
@ -83,8 +82,7 @@ class StaticInitialisationOfSerializedObjectTest {
|
|||||||
fun deserializeTest() {
|
fun deserializeTest() {
|
||||||
data class D(val c: C2)
|
data class D(val c: C2)
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource("StaticInitialisationOfSerializedObjectTest.deserializeTest")
|
val url = EvolvabilityTests::class.java.getResource("StaticInitialisationOfSerializedObjectTest.deserializeTest")
|
||||||
val f = File(path.toURI())
|
|
||||||
|
|
||||||
// Original version of the class for the serialised version of this class
|
// Original version of the class for the serialised version of this class
|
||||||
//
|
//
|
||||||
@ -100,9 +98,9 @@ class StaticInitialisationOfSerializedObjectTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val sf2 = SerializerFactory(WL(), ClassLoader.getSystemClassLoader())
|
val sf2 = SerializerFactory(WL(), ClassLoader.getSystemClassLoader())
|
||||||
val bytes = f.readBytes()
|
val bytes = url.readBytes()
|
||||||
|
|
||||||
Assertions.assertThatThrownBy {
|
assertThatThrownBy {
|
||||||
DeserializationInput(sf2).deserialize(SerializedBytes<D>(bytes))
|
DeserializationInput(sf2).deserialize(SerializedBytes<D>(bytes))
|
||||||
}.isInstanceOf(NotSerializableException::class.java)
|
}.isInstanceOf(NotSerializableException::class.java)
|
||||||
}
|
}
|
||||||
@ -119,8 +117,7 @@ class StaticInitialisationOfSerializedObjectTest {
|
|||||||
fun deserializeTest2() {
|
fun deserializeTest2() {
|
||||||
data class D(val c: C2)
|
data class D(val c: C2)
|
||||||
|
|
||||||
val path = EvolvabilityTests::class.java.getResource("StaticInitialisationOfSerializedObjectTest.deserializeTest2")
|
val url = EvolvabilityTests::class.java.getResource("StaticInitialisationOfSerializedObjectTest.deserializeTest2")
|
||||||
val f = File(path.toURI())
|
|
||||||
|
|
||||||
// Original version of the class for the serialised version of this class
|
// Original version of the class for the serialised version of this class
|
||||||
//
|
//
|
||||||
@ -142,12 +139,12 @@ class StaticInitialisationOfSerializedObjectTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val sf2 = TestSerializerFactory(WL1(), WL2())
|
val sf2 = TestSerializerFactory(WL1(), WL2())
|
||||||
val bytes = f.readBytes()
|
val bytes = url.readBytes()
|
||||||
|
|
||||||
// Deserializing should throw because C is not on the whitelist NOT because
|
// Deserializing should throw because C is not on the whitelist NOT because
|
||||||
// we ever went anywhere near statically constructing it prior to not actually
|
// we ever went anywhere near statically constructing it prior to not actually
|
||||||
// creating an instance of it
|
// creating an instance of it
|
||||||
Assertions.assertThatThrownBy {
|
assertThatThrownBy {
|
||||||
DeserializationInput(sf2).deserialize(SerializedBytes<D>(bytes))
|
DeserializationInput(sf2).deserialize(SerializedBytes<D>(bytes))
|
||||||
}.isInstanceOf(NotSerializableException::class.java)
|
}.isInstanceOf(NotSerializableException::class.java)
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,8 @@ import net.corda.client.rpc.CordaRPCClient
|
|||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.StartableByRPC
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
|
import net.corda.core.internal.list
|
||||||
|
import net.corda.core.internal.readLines
|
||||||
import net.corda.core.messaging.startFlow
|
import net.corda.core.messaging.startFlow
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.node.internal.NodeStartup
|
import net.corda.node.internal.NodeStartup
|
||||||
@ -35,7 +37,6 @@ import org.assertj.core.api.Assertions.assertThatThrownBy
|
|||||||
import org.junit.ClassRule
|
import org.junit.ClassRule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.nio.file.Files
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class BootTests : IntegrationTest() {
|
class BootTests : IntegrationTest() {
|
||||||
@ -63,13 +64,13 @@ class BootTests : IntegrationTest() {
|
|||||||
driver(DriverParameters(isDebug = true, systemProperties = mapOf("log4j.configurationFile" to logConfigFile.toString()))) {
|
driver(DriverParameters(isDebug = true, systemProperties = mapOf("log4j.configurationFile" to logConfigFile.toString()))) {
|
||||||
val alice = startNode(providedName = ALICE_NAME).get()
|
val alice = startNode(providedName = ALICE_NAME).get()
|
||||||
val logFolder = alice.baseDirectory / NodeStartup.LOGS_DIRECTORY_NAME
|
val logFolder = alice.baseDirectory / NodeStartup.LOGS_DIRECTORY_NAME
|
||||||
val logFile = logFolder.toFile().listFiles { _, name -> name.endsWith(".log") }.single()
|
val logFile = logFolder.list { it.filter { it.fileName.toString().endsWith(".log") }.findAny().get() }
|
||||||
// Start second Alice, should fail
|
// Start second Alice, should fail
|
||||||
assertThatThrownBy {
|
assertThatThrownBy {
|
||||||
startNode(providedName = ALICE_NAME).getOrThrow()
|
startNode(providedName = ALICE_NAME).getOrThrow()
|
||||||
}
|
}
|
||||||
// We count the number of nodes that wrote into the logfile by counting "Logs can be found in"
|
// We count the number of nodes that wrote into the logfile by counting "Logs can be found in"
|
||||||
val numberOfNodesThatLogged = Files.lines(logFile.toPath()).filter { NodeStartup.LOGS_CAN_BE_FOUND_IN_STRING in it }.count()
|
val numberOfNodesThatLogged = logFile.readLines { it.filter { NodeStartup.LOGS_CAN_BE_FOUND_IN_STRING in it }.count() }
|
||||||
assertEquals(1, numberOfNodesThatLogged)
|
assertEquals(1, numberOfNodesThatLogged)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,57 +14,56 @@ import com.typesafe.config.Config
|
|||||||
import com.typesafe.config.ConfigException
|
import com.typesafe.config.ConfigException
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import com.typesafe.config.ConfigRenderOptions
|
import com.typesafe.config.ConfigRenderOptions
|
||||||
|
import net.corda.core.internal.div
|
||||||
|
import net.corda.core.internal.writeText
|
||||||
import net.corda.node.internal.cordapp.CordappConfigFileProvider
|
import net.corda.node.internal.cordapp.CordappConfigFileProvider
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.io.File
|
import java.nio.file.Paths
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
|
||||||
|
|
||||||
class CordappConfigFileProviderTests {
|
class CordappConfigFileProviderTests {
|
||||||
private companion object {
|
private companion object {
|
||||||
val cordappConfDir = File("build/tmp/cordapps/config")
|
val cordappConfDir = Paths.get("build") / "tmp" / "cordapps" / "config"
|
||||||
val cordappName = "test"
|
const val cordappName = "test"
|
||||||
val cordappConfFile = File(cordappConfDir, cordappName + ".conf").toPath()
|
val cordappConfFile = cordappConfDir / "$cordappName.conf"
|
||||||
|
|
||||||
val validConfig = ConfigFactory.parseString("key=value")
|
val validConfig: Config = ConfigFactory.parseString("key=value")
|
||||||
val alternateValidConfig = ConfigFactory.parseString("key=alternateValue")
|
val alternateValidConfig: Config = ConfigFactory.parseString("key=alternateValue")
|
||||||
val invalidConfig = "Invalid"
|
const val invalidConfig = "Invalid"
|
||||||
}
|
}
|
||||||
|
|
||||||
val provider = CordappConfigFileProvider(cordappConfDir)
|
private val provider = CordappConfigFileProvider(cordappConfDir)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test that config can be loaded`() {
|
fun `test that config can be loaded`() {
|
||||||
writeConfig(validConfig, cordappConfFile)
|
writeConfig(validConfig)
|
||||||
assertThat(provider.getConfigByName(cordappName)).isEqualTo(validConfig)
|
assertThat(provider.getConfigByName(cordappName)).isEqualTo(validConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `config is idempotent if the underlying file is not changed`() {
|
fun `config is idempotent if the underlying file is not changed`() {
|
||||||
writeConfig(validConfig, cordappConfFile)
|
writeConfig(validConfig)
|
||||||
assertThat(provider.getConfigByName(cordappName)).isEqualTo(validConfig)
|
assertThat(provider.getConfigByName(cordappName)).isEqualTo(validConfig)
|
||||||
assertThat(provider.getConfigByName(cordappName)).isEqualTo(validConfig)
|
assertThat(provider.getConfigByName(cordappName)).isEqualTo(validConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `config is not idempotent if the underlying file is changed`() {
|
fun `config is not idempotent if the underlying file is changed`() {
|
||||||
writeConfig(validConfig, cordappConfFile)
|
writeConfig(validConfig)
|
||||||
assertThat(provider.getConfigByName(cordappName)).isEqualTo(validConfig)
|
assertThat(provider.getConfigByName(cordappName)).isEqualTo(validConfig)
|
||||||
|
|
||||||
writeConfig(alternateValidConfig, cordappConfFile)
|
writeConfig(alternateValidConfig)
|
||||||
assertThat(provider.getConfigByName(cordappName)).isEqualTo(alternateValidConfig)
|
assertThat(provider.getConfigByName(cordappName)).isEqualTo(alternateValidConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = ConfigException.Parse::class)
|
@Test(expected = ConfigException.Parse::class)
|
||||||
fun `an invalid config throws an exception`() {
|
fun `an invalid config throws an exception`() {
|
||||||
Files.write(cordappConfFile, invalidConfig.toByteArray())
|
cordappConfFile.writeText(invalidConfig)
|
||||||
|
|
||||||
provider.getConfigByName(cordappName)
|
provider.getConfigByName(cordappName)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the config to the path provided - will (and must) overwrite any existing config
|
* Writes the config to the path provided - will (and must) overwrite any existing config
|
||||||
*/
|
*/
|
||||||
private fun writeConfig(config: Config, to: Path) = Files.write(cordappConfFile, config.root().render(ConfigRenderOptions.concise()).toByteArray())
|
private fun writeConfig(config: Config) = cordappConfFile.writeText(config.root().render(ConfigRenderOptions.concise()))
|
||||||
}
|
}
|
@ -18,6 +18,7 @@ import net.corda.core.flows.FlowLogic
|
|||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.concurrent.transpose
|
import net.corda.core.internal.concurrent.transpose
|
||||||
|
import net.corda.core.internal.copyTo
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.toLedgerTransaction
|
import net.corda.core.internal.toLedgerTransaction
|
||||||
@ -44,7 +45,6 @@ import org.junit.ClassRule
|
|||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.nio.file.Files
|
|
||||||
import kotlin.test.assertFailsWith
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
class AttachmentLoadingTests : IntegrationTest() {
|
class AttachmentLoadingTests : IntegrationTest() {
|
||||||
@ -65,7 +65,7 @@ class AttachmentLoadingTests : IntegrationTest() {
|
|||||||
|
|
||||||
private val logger = contextLogger()
|
private val logger = contextLogger()
|
||||||
val isolatedJAR = AttachmentLoadingTests::class.java.getResource("isolated.jar")!!
|
val isolatedJAR = AttachmentLoadingTests::class.java.getResource("isolated.jar")!!
|
||||||
val ISOLATED_CONTRACT_ID = "net.corda.finance.contracts.isolated.AnotherDummyContract"
|
const val ISOLATED_CONTRACT_ID = "net.corda.finance.contracts.isolated.AnotherDummyContract"
|
||||||
|
|
||||||
val bankAName = CordaX500Name("BankA", "Zurich", "CH")
|
val bankAName = CordaX500Name("BankA", "Zurich", "CH")
|
||||||
val bankBName = CordaX500Name("BankB", "Zurich", "CH")
|
val bankBName = CordaX500Name("BankB", "Zurich", "CH")
|
||||||
@ -85,11 +85,7 @@ class AttachmentLoadingTests : IntegrationTest() {
|
|||||||
// Copy the app jar to the first node. The second won't have it.
|
// Copy the app jar to the first node. The second won't have it.
|
||||||
val path = (baseDirectory(nodeName) / "cordapps").createDirectories() / "isolated.jar"
|
val path = (baseDirectory(nodeName) / "cordapps").createDirectories() / "isolated.jar"
|
||||||
logger.info("Installing isolated jar to $path")
|
logger.info("Installing isolated jar to $path")
|
||||||
isolatedJAR.openStream().buffered().use { input ->
|
isolatedJAR.openStream().use { it.copyTo(path) }
|
||||||
Files.newOutputStream(path).buffered().use { output ->
|
|
||||||
input.copyTo(output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +39,6 @@ import org.junit.*
|
|||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import kotlin.streams.toList
|
|
||||||
|
|
||||||
class NetworkMapTest : IntegrationTest() {
|
class NetworkMapTest : IntegrationTest() {
|
||||||
companion object {
|
companion object {
|
||||||
@ -216,7 +215,7 @@ class NetworkMapTest : IntegrationTest() {
|
|||||||
// Make sure the nodes aren't getting the node infos from their additional directories
|
// Make sure the nodes aren't getting the node infos from their additional directories
|
||||||
val nodeInfosDir = baseDirectory / CordformNode.NODE_INFO_DIRECTORY
|
val nodeInfosDir = baseDirectory / CordformNode.NODE_INFO_DIRECTORY
|
||||||
if (nodeInfosDir.exists()) {
|
if (nodeInfosDir.exists()) {
|
||||||
assertThat(nodeInfosDir.list { it.toList() }).isEmpty()
|
assertThat(nodeInfosDir.list()).isEmpty()
|
||||||
}
|
}
|
||||||
assertThat(rpc.networkMapSnapshot()).containsOnly(*nodes)
|
assertThat(rpc.networkMapSnapshot()).containsOnly(*nodes)
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import com.google.common.jimfs.Jimfs
|
|||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
|
import net.corda.core.internal.size
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.node.services.KeyManagementService
|
import net.corda.core.node.services.KeyManagementService
|
||||||
import net.corda.nodeapi.internal.NodeInfoAndSigned
|
import net.corda.nodeapi.internal.NodeInfoAndSigned
|
||||||
@ -25,7 +26,6 @@ import net.corda.testing.internal.createNodeInfoAndSigned
|
|||||||
import net.corda.testing.node.internal.MockKeyManagementService
|
import net.corda.testing.node.internal.MockKeyManagementService
|
||||||
import net.corda.testing.node.makeTestIdentityService
|
import net.corda.testing.node.makeTestIdentityService
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.assertj.core.api.Assertions.contentOf
|
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@ -75,9 +75,9 @@ class NodeInfoWatcherTest {
|
|||||||
assertEquals(1, nodeInfoFiles.size)
|
assertEquals(1, nodeInfoFiles.size)
|
||||||
val fileName = nodeInfoFiles.first()
|
val fileName = nodeInfoFiles.first()
|
||||||
assertTrue(fileName.startsWith(NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX))
|
assertTrue(fileName.startsWith(NodeInfoFilesCopier.NODE_INFO_FILE_NAME_PREFIX))
|
||||||
val file = (tempFolder.root.path / fileName).toFile()
|
val file = (tempFolder.root.path / fileName)
|
||||||
// Just check that something is written, another tests verifies that the written value can be read back.
|
// Just check that something is written, another tests verifies that the written value can be read back.
|
||||||
assertThat(contentOf(file)).isNotEmpty()
|
assertThat(file.size).isGreaterThan(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -103,7 +103,7 @@ class MQSecurityAsNodeTest : P2PMQSecurityTest() {
|
|||||||
val legalName = CordaX500Name("MegaCorp", "London", "GB")
|
val legalName = CordaX500Name("MegaCorp", "London", "GB")
|
||||||
certificatesDirectory.createDirectories()
|
certificatesDirectory.createDirectories()
|
||||||
if (!trustStoreFile.exists()) {
|
if (!trustStoreFile.exists()) {
|
||||||
javaClass.classLoader.getResourceAsStream("certificates/cordatruststore.jks").copyTo(trustStoreFile)
|
javaClass.classLoader.getResourceAsStream("certificates/cordatruststore.jks").use { it.copyTo(trustStoreFile) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val clientKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
val clientKeyPair = Crypto.generateKeyPair(X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME)
|
||||||
|
@ -12,33 +12,34 @@ package net.corda.node.internal.cordapp
|
|||||||
|
|
||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import net.corda.core.utilities.loggerFor
|
import net.corda.core.internal.createDirectories
|
||||||
import java.io.File
|
import net.corda.core.internal.div
|
||||||
|
import net.corda.core.internal.exists
|
||||||
|
import net.corda.core.internal.isDirectory
|
||||||
|
import net.corda.core.utilities.contextLogger
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
class CordappConfigFileProvider(val configDir: File = DEFAULT_CORDAPP_CONFIG_DIR) : CordappConfigProvider {
|
class CordappConfigFileProvider(private val configDir: Path = DEFAULT_CORDAPP_CONFIG_DIR) : CordappConfigProvider {
|
||||||
companion object {
|
companion object {
|
||||||
val DEFAULT_CORDAPP_CONFIG_DIR = File("cordapps/config")
|
val DEFAULT_CORDAPP_CONFIG_DIR = Paths.get("cordapps") / "config"
|
||||||
val CONFIG_EXT = ".conf"
|
const val CONFIG_EXT = ".conf"
|
||||||
val logger = loggerFor<CordappConfigFileProvider>()
|
val logger = contextLogger()
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
configDir.mkdirs()
|
configDir.createDirectories()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getConfigByName(name: String): Config {
|
override fun getConfigByName(name: String): Config {
|
||||||
val configFile = File(configDir, name + CONFIG_EXT)
|
val configFile = configDir / "$name$CONFIG_EXT"
|
||||||
return if (configFile.exists()) {
|
return if (configFile.exists()) {
|
||||||
if (configFile.isDirectory) {
|
check(!configFile.isDirectory()) { "${configFile.toAbsolutePath()} is a directory, expected a config file" }
|
||||||
throw IllegalStateException("File at ${configFile.absolutePath} is a directory, expected a config file")
|
logger.info("Found config for cordapp $name in ${configFile.toAbsolutePath()}")
|
||||||
} else {
|
ConfigFactory.parseFile(configFile.toFile())
|
||||||
logger.info("Found config for cordapp $name in ${configFile.absolutePath}")
|
|
||||||
ConfigFactory.parseFile(configFile)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
logger.info("No config found for cordapp $name in ${configFile.absolutePath}")
|
logger.info("No config found for cordapp $name in ${configFile.toAbsolutePath()}")
|
||||||
ConfigFactory.empty()
|
ConfigFactory.empty()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@ -30,15 +30,13 @@ import net.corda.node.services.config.NodeConfiguration
|
|||||||
import net.corda.nodeapi.internal.coreContractClasses
|
import net.corda.nodeapi.internal.coreContractClasses
|
||||||
import net.corda.nodeapi.internal.serialization.DefaultWhitelist
|
import net.corda.nodeapi.internal.serialization.DefaultWhitelist
|
||||||
import org.apache.commons.collections4.map.LRUMap
|
import org.apache.commons.collections4.map.LRUMap
|
||||||
import java.io.File
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
import java.net.JarURLConnection
|
import java.net.JarURLConnection
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
import java.nio.file.Paths
|
||||||
import java.nio.file.attribute.FileTime
|
import java.nio.file.attribute.FileTime
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -88,8 +86,7 @@ class CordappLoader private constructor(private val cordappJarPaths: List<Restri
|
|||||||
* Create a dev mode CordappLoader for test environments that creates and loads cordapps from the classpath
|
* Create a dev mode CordappLoader for test environments that creates and loads cordapps from the classpath
|
||||||
* and cordapps directory. This is intended mostly for use by the driver.
|
* and cordapps directory. This is intended mostly for use by the driver.
|
||||||
*
|
*
|
||||||
* @param baseDir See [createDefault.baseDir]
|
* @param testPackages See [createWithTestPackages]
|
||||||
* @param testPackages See [createWithTestPackages.testPackages]
|
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
fun createDefaultWithTestPackages(configuration: NodeConfiguration, testPackages: List<String>): CordappLoader {
|
fun createDefaultWithTestPackages(configuration: NodeConfiguration, testPackages: List<String>): CordappLoader {
|
||||||
@ -139,31 +136,26 @@ class CordappLoader private constructor(private val cordappJarPaths: List<Restri
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Takes a package of classes and creates a JAR from them - only use in tests. */
|
/** Takes a package of classes and creates a JAR from them - only use in tests. */
|
||||||
private fun createDevCordappJar(scanPackage: String, path: URL, jarPackageName: String): URI {
|
private fun createDevCordappJar(scanPackage: String, url: URL, jarPackageName: String): URI {
|
||||||
if (!generatedCordapps.contains(path)) {
|
return generatedCordapps.computeIfAbsent(url) {
|
||||||
val cordappDir = File("build/tmp/generated-test-cordapps")
|
val cordappDir = (Paths.get("build") / "tmp" / "generated-test-cordapps").createDirectories()
|
||||||
cordappDir.mkdirs()
|
val cordappJAR = cordappDir / "$scanPackage-${UUID.randomUUID()}.jar"
|
||||||
val cordappJAR = File(cordappDir, "$scanPackage-${UUID.randomUUID()}.jar")
|
|
||||||
logger.info("Generating a test-only cordapp of classes discovered in $scanPackage at $cordappJAR")
|
logger.info("Generating a test-only cordapp of classes discovered in $scanPackage at $cordappJAR")
|
||||||
FileOutputStream(cordappJAR).use {
|
JarOutputStream(cordappJAR.outputStream()).use { jos ->
|
||||||
JarOutputStream(it).use { jos ->
|
val scanDir = url.toPath()
|
||||||
val scanDir = File(path.toURI())
|
scanDir.walk { it.forEach {
|
||||||
scanDir.walkTopDown().forEach {
|
val entryPath = "$jarPackageName/${scanDir.relativize(it).toString().replace('\\', '/')}"
|
||||||
val entryPath = jarPackageName + "/" + scanDir.toPath().relativize(it.toPath()).toString().replace('\\', '/')
|
val time = FileTime.from(Instant.EPOCH)
|
||||||
val time = FileTime.from(Instant.EPOCH)
|
val entry = ZipEntry(entryPath).setCreationTime(time).setLastAccessTime(time).setLastModifiedTime(time)
|
||||||
val entry = ZipEntry(entryPath).setCreationTime(time).setLastAccessTime(time).setLastModifiedTime(time)
|
jos.putNextEntry(entry)
|
||||||
jos.putNextEntry(entry)
|
if (it.isRegularFile()) {
|
||||||
if (it.isFile) {
|
it.copyTo(jos)
|
||||||
Files.copy(it.toPath(), jos)
|
|
||||||
}
|
|
||||||
jos.closeEntry()
|
|
||||||
}
|
}
|
||||||
}
|
jos.closeEntry()
|
||||||
|
} }
|
||||||
}
|
}
|
||||||
generatedCordapps[path] = cordappJAR.toURI()
|
cordappJAR.toUri()
|
||||||
}
|
}
|
||||||
|
|
||||||
return generatedCordapps[path]!!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCordappsInDirectory(cordappsDir: Path): List<RestrictedURL> {
|
private fun getCordappsInDirectory(cordappsDir: Path): List<RestrictedURL> {
|
||||||
|
@ -20,10 +20,7 @@ import net.corda.core.concurrent.CordaFuture
|
|||||||
import net.corda.core.context.InvocationContext
|
import net.corda.core.context.InvocationContext
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.*
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.FlowIORequest
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.FlowStateMachine
|
|
||||||
import net.corda.core.internal.isRegularFile
|
|
||||||
import net.corda.core.internal.uncheckedCast
|
|
||||||
import net.corda.core.serialization.SerializationContext
|
import net.corda.core.serialization.SerializationContext
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.core.utilities.Try
|
import net.corda.core.utilities.Try
|
||||||
@ -41,7 +38,6 @@ import net.corda.nodeapi.internal.persistence.contextTransaction
|
|||||||
import net.corda.nodeapi.internal.persistence.contextTransactionOrNull
|
import net.corda.nodeapi.internal.persistence.contextTransactionOrNull
|
||||||
import org.slf4j.Logger
|
import org.slf4j.Logger
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.nio.file.Paths
|
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.reflect.KProperty1
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
@ -309,7 +305,7 @@ val Class<out FlowLogic<*>>.flowVersionAndInitiatingClass: Pair<Int, Class<out F
|
|||||||
|
|
||||||
val Class<out FlowLogic<*>>.appName: String
|
val Class<out FlowLogic<*>>.appName: String
|
||||||
get() {
|
get() {
|
||||||
val jarFile = Paths.get(protectionDomain.codeSource.location.toURI())
|
val jarFile = protectionDomain.codeSource.location.toPath()
|
||||||
return if (jarFile.isRegularFile() && jarFile.toString().endsWith(".jar")) {
|
return if (jarFile.isRegularFile() && jarFile.toString().endsWith(".jar")) {
|
||||||
jarFile.fileName.toString().removeSuffix(".jar")
|
jarFile.fileName.toString().removeSuffix(".jar")
|
||||||
} else {
|
} else {
|
||||||
|
@ -11,10 +11,10 @@
|
|||||||
package net.corda.node.services.transactions
|
package net.corda.node.services.transactions
|
||||||
|
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
|
import net.corda.core.internal.writer
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.core.utilities.debug
|
import net.corda.core.utilities.debug
|
||||||
import java.io.FileWriter
|
|
||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
@ -58,7 +58,7 @@ class BFTSMaRtConfig(private val replicaAddresses: List<NetworkHostAndPort>, deb
|
|||||||
|
|
||||||
private fun configWriter(name: String, block: PrintWriter.() -> Unit) {
|
private fun configWriter(name: String, block: PrintWriter.() -> Unit) {
|
||||||
// Default charset, consistent with loaders:
|
// Default charset, consistent with loaders:
|
||||||
FileWriter((path / name).toFile()).use {
|
(path / name).writer().use {
|
||||||
PrintWriter(it).use {
|
PrintWriter(it).use {
|
||||||
it.run(block)
|
it.run(block)
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
package net.corda.node.services.transactions
|
package net.corda.node.services.transactions
|
||||||
|
|
||||||
|
import net.corda.core.internal.deleteRecursively
|
||||||
import net.corda.core.internal.uncheckedCast
|
import net.corda.core.internal.uncheckedCast
|
||||||
import net.corda.nodeapi.internal.addShutdownHook
|
import net.corda.nodeapi.internal.addShutdownHook
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
@ -19,7 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger
|
|||||||
private class DeleteOnExitPath(internal val path: Path) {
|
private class DeleteOnExitPath(internal val path: Path) {
|
||||||
private val shutdownHook = addShutdownHook { dispose() }
|
private val shutdownHook = addShutdownHook { dispose() }
|
||||||
internal fun dispose() {
|
internal fun dispose() {
|
||||||
path.toFile().deleteRecursively()
|
path.deleteRecursively()
|
||||||
shutdownHook.cancel()
|
shutdownHook.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ class RaftUniquenessProvider(
|
|||||||
get() = _clientFuture.get()
|
get() = _clientFuture.get()
|
||||||
|
|
||||||
fun start() {
|
fun start() {
|
||||||
log.info("Creating Copycat server, log stored in: ${storagePath.toFile()}")
|
log.info("Creating Copycat server, log stored in: ${storagePath.toAbsolutePath()}")
|
||||||
val stateMachineFactory = {
|
val stateMachineFactory = {
|
||||||
RaftTransactionCommitLog(db, clock, RaftUniquenessProvider.Companion::createMap)
|
RaftTransactionCommitLog(db, clock, RaftUniquenessProvider.Companion::createMap)
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ package net.corda.node.utilities
|
|||||||
import com.ea.agentloader.AgentLoader
|
import com.ea.agentloader.AgentLoader
|
||||||
import net.corda.core.internal.exists
|
import net.corda.core.internal.exists
|
||||||
import net.corda.core.internal.isRegularFile
|
import net.corda.core.internal.isRegularFile
|
||||||
|
import net.corda.core.internal.toPath
|
||||||
|
import java.net.URL
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
@ -53,7 +55,7 @@ object JVMAgentRegistry {
|
|||||||
} else {
|
} else {
|
||||||
(this::class.java.classLoader as? URLClassLoader)
|
(this::class.java.classLoader as? URLClassLoader)
|
||||||
?.urLs
|
?.urLs
|
||||||
?.map { Paths.get(it.toURI()) }
|
?.map(URL::toPath)
|
||||||
?.firstOrNull { it.fileName.toString() == jarFileName }
|
?.firstOrNull { it.fileName.toString() == jarFileName }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
package net.corda.node
|
package net.corda.node
|
||||||
|
|
||||||
import joptsimple.OptionException
|
import joptsimple.OptionException
|
||||||
|
import net.corda.core.internal.delete
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.nodeapi.internal.crypto.X509KeyStore
|
import net.corda.nodeapi.internal.crypto.X509KeyStore
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
@ -18,7 +19,6 @@ import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
|||||||
import org.junit.BeforeClass
|
import org.junit.BeforeClass
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.slf4j.event.Level
|
import org.slf4j.event.Level
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -150,7 +150,7 @@ class ArgsParserTest {
|
|||||||
assertEquals(truststorePath.toAbsolutePath(), cmdLineOptions.nodeRegistrationOption?.networkRootTrustStorePath)
|
assertEquals(truststorePath.toAbsolutePath(), cmdLineOptions.nodeRegistrationOption?.networkRootTrustStorePath)
|
||||||
assertEquals("password-test", cmdLineOptions.nodeRegistrationOption?.networkRootTrustStorePassword)
|
assertEquals("password-test", cmdLineOptions.nodeRegistrationOption?.networkRootTrustStorePassword)
|
||||||
} finally {
|
} finally {
|
||||||
Files.delete(truststorePath)
|
truststorePath.delete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,9 +13,10 @@ package net.corda.node.internal
|
|||||||
import com.nhaarman.mockito_kotlin.doReturn
|
import com.nhaarman.mockito_kotlin.doReturn
|
||||||
import com.nhaarman.mockito_kotlin.whenever
|
import com.nhaarman.mockito_kotlin.whenever
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.internal.delete
|
||||||
|
import net.corda.core.internal.list
|
||||||
import net.corda.core.internal.readObject
|
import net.corda.core.internal.readObject
|
||||||
import net.corda.core.node.NodeInfo
|
import net.corda.core.node.NodeInfo
|
||||||
import net.corda.core.serialization.deserialize
|
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.node.VersionInfo
|
import net.corda.node.VersionInfo
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
@ -28,7 +29,7 @@ import net.corda.testing.node.MockServices.Companion.makeTestDataSourcePropertie
|
|||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.rules.TemporaryFolder
|
import org.junit.rules.TemporaryFolder
|
||||||
import java.nio.file.Files
|
import java.nio.file.Path
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
|
|
||||||
@ -42,14 +43,21 @@ class NodeTest {
|
|||||||
@JvmField
|
@JvmField
|
||||||
val testSerialization = SerializationEnvironmentRule()
|
val testSerialization = SerializationEnvironmentRule()
|
||||||
|
|
||||||
private fun nodeInfoFile() = temporaryFolder.root.listFiles().singleOrNull { it.name.startsWith(NODE_INFO_FILE_NAME_PREFIX) }
|
private fun nodeInfoFile(): Path? {
|
||||||
|
return temporaryFolder.root.toPath().list { paths ->
|
||||||
|
paths.filter { it.fileName.toString().startsWith(NODE_INFO_FILE_NAME_PREFIX) }.findAny().orElse(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun AbstractNode.generateNodeInfo(): NodeInfo {
|
private fun AbstractNode.generateNodeInfo(): NodeInfo {
|
||||||
assertNull(nodeInfoFile())
|
assertNull(nodeInfoFile())
|
||||||
generateAndSaveNodeInfo()
|
generateAndSaveNodeInfo()
|
||||||
val path = nodeInfoFile()!!.toPath()
|
val path = nodeInfoFile()!!
|
||||||
val nodeInfo = path.readObject<SignedNodeInfo>().raw.deserialize()
|
try {
|
||||||
Files.delete(path)
|
return path.readObject<SignedNodeInfo>().verified()
|
||||||
return nodeInfo
|
} finally {
|
||||||
|
path.delete()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -38,8 +38,8 @@ import com.opengamma.strata.report.ReportCalculationResults
|
|||||||
import com.opengamma.strata.report.trade.TradeReport
|
import com.opengamma.strata.report.trade.TradeReport
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.exists
|
import net.corda.core.internal.exists
|
||||||
|
import net.corda.core.internal.toPath
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,7 +69,7 @@ class SwapPricingCcpExample {
|
|||||||
*/
|
*/
|
||||||
private val resourcesUri = run {
|
private val resourcesUri = run {
|
||||||
// Find src/main/resources by walking up the directory tree starting at a classpath root:
|
// Find src/main/resources by walking up the directory tree starting at a classpath root:
|
||||||
var module = Paths.get(javaClass.getResource("/").toURI())
|
var module = javaClass.getResource("/").toPath()
|
||||||
val relative = "src" / "main" / "resources"
|
val relative = "src" / "main" / "resources"
|
||||||
var path: Path
|
var path: Path
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -10,11 +10,12 @@
|
|||||||
|
|
||||||
package net.corda.testing.node.internal
|
package net.corda.testing.node.internal
|
||||||
|
|
||||||
import org.apache.commons.io.FileUtils
|
import net.corda.core.internal.readText
|
||||||
|
import net.corda.core.internal.writeText
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.rules.TemporaryFolder
|
import org.junit.rules.TemporaryFolder
|
||||||
import java.io.File
|
import java.nio.file.Paths
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
@ -31,8 +32,7 @@ class ProcessUtilitiesTests {
|
|||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val fileNameToCreate = args[0]
|
Paths.get(args[0]).writeText(tmpString)
|
||||||
FileUtils.write(File(fileNameToCreate), tmpString)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,6 +41,6 @@ class ProcessUtilitiesTests {
|
|||||||
val tmpFile = tempFolder.newFile("${ProcessUtilitiesTests::class.java.simpleName}.txt")
|
val tmpFile = tempFolder.newFile("${ProcessUtilitiesTests::class.java.simpleName}.txt")
|
||||||
val startedProcess = ProcessUtilities.startJavaProcess<ProcessUtilitiesTests>(listOf(tmpFile.absolutePath))
|
val startedProcess = ProcessUtilities.startJavaProcess<ProcessUtilitiesTests>(listOf(tmpFile.absolutePath))
|
||||||
assertTrue { startedProcess.waitFor(20, TimeUnit.SECONDS) }
|
assertTrue { startedProcess.waitFor(20, TimeUnit.SECONDS) }
|
||||||
assertEquals(tmpString, FileUtils.readFileToString(tmpFile))
|
assertEquals(tmpString, tmpFile.toPath().readText())
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -73,8 +73,6 @@ import java.net.ConnectException
|
|||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
|
||||||
import java.nio.file.StandardCopyOption
|
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@ -136,7 +134,7 @@ class DriverDSLImpl(
|
|||||||
val urls = (cl as URLClassLoader).urLs
|
val urls = (cl as URLClassLoader).urLs
|
||||||
val jarPattern = jarNamePattern.toRegex()
|
val jarPattern = jarNamePattern.toRegex()
|
||||||
val jarFileUrl = urls.first { jarPattern.matches(it.path) }
|
val jarFileUrl = urls.first { jarPattern.matches(it.path) }
|
||||||
Paths.get(jarFileUrl.toURI()).toString()
|
jarFileUrl.toPath().toString()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
log.warn("Unable to locate JAR `$jarNamePattern` on classpath: ${e.message}", e)
|
log.warn("Unable to locate JAR `$jarNamePattern` on classpath: ${e.message}", e)
|
||||||
throw e
|
throw e
|
||||||
@ -1094,16 +1092,11 @@ fun getTimestampAsDirectoryName(): String {
|
|||||||
|
|
||||||
fun writeConfig(path: Path, filename: String, config: Config) {
|
fun writeConfig(path: Path, filename: String, config: Config) {
|
||||||
val configString = config.root().render(ConfigRenderOptions.defaults())
|
val configString = config.root().render(ConfigRenderOptions.defaults())
|
||||||
configString.byteInputStream().copyTo(path / filename, StandardCopyOption.REPLACE_EXISTING)
|
(path / filename).writeText(configString)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Config.toNodeOnly(): Config {
|
private fun Config.toNodeOnly(): Config {
|
||||||
|
return if (hasPath("webAddress")) withoutPath("webAddress").withoutPath("useHTTPS") else this
|
||||||
return if (hasPath("webAddress")) {
|
|
||||||
withoutPath("webAddress").withoutPath("useHTTPS")
|
|
||||||
} else {
|
|
||||||
this
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private operator fun Config.plus(property: Pair<String, Any>) = withValue(property.first, ConfigValueFactory.fromAnyRef(property.second))
|
private operator fun Config.plus(property: Pair<String, Any>) = withValue(property.first, ConfigValueFactory.fromAnyRef(property.second))
|
@ -12,6 +12,7 @@ package net.corda.testing.node.internal.demorun
|
|||||||
|
|
||||||
import net.corda.cordform.CordformDefinition
|
import net.corda.cordform.CordformDefinition
|
||||||
import net.corda.cordform.CordformNode
|
import net.corda.cordform.CordformNode
|
||||||
|
import net.corda.core.internal.deleteRecursively
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.testing.driver.JmxPolicy
|
import net.corda.testing.driver.JmxPolicy
|
||||||
@ -39,7 +40,7 @@ class CordformNodeRunner(val cordformDefinition: CordformDefinition) {
|
|||||||
|
|
||||||
fun clean() {
|
fun clean() {
|
||||||
System.err.println("Deleting: ${cordformDefinition.nodesDirectory}")
|
System.err.println("Deleting: ${cordformDefinition.nodesDirectory}")
|
||||||
cordformDefinition.nodesDirectory.toFile().deleteRecursively()
|
cordformDefinition.nodesDirectory.deleteRecursively()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,17 +13,13 @@ package net.corda.smoketesting
|
|||||||
import net.corda.client.rpc.CordaRPCClient
|
import net.corda.client.rpc.CordaRPCClient
|
||||||
import net.corda.client.rpc.CordaRPCConnection
|
import net.corda.client.rpc.CordaRPCConnection
|
||||||
import net.corda.client.rpc.internal.KryoClientSerializationScheme
|
import net.corda.client.rpc.internal.KryoClientSerializationScheme
|
||||||
import net.corda.core.internal.copyTo
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.copyToDirectory
|
|
||||||
import net.corda.core.internal.createDirectories
|
|
||||||
import net.corda.core.internal.div
|
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.nodeapi.internal.network.NetworkParametersCopier
|
import net.corda.nodeapi.internal.network.NetworkParametersCopier
|
||||||
import net.corda.testing.common.internal.asContextEnv
|
import net.corda.testing.common.internal.asContextEnv
|
||||||
import net.corda.testing.common.internal.testNetworkParameters
|
import net.corda.testing.common.internal.testNetworkParameters
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URL
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@ -57,20 +53,21 @@ class NodeProcess(
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.info("Deleting Artemis directories, because they're large!")
|
log.info("Deleting Artemis directories, because they're large!")
|
||||||
(nodeDir / "artemis").toFile().deleteRecursively()
|
(nodeDir / "artemis").deleteRecursively()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO All use of this factory have duplicate code which is either bundling the calling module or a 3rd party module
|
// TODO All use of this factory have duplicate code which is either bundling the calling module or a 3rd party module
|
||||||
// as a CorDapp for the nodes.
|
// as a CorDapp for the nodes.
|
||||||
class Factory(
|
class Factory(
|
||||||
private val buildDirectory: Path = Paths.get("build"),
|
private val buildDirectory: Path = Paths.get("build"),
|
||||||
private val cordaJarUrl: URL? = this::class.java.getResource("/corda.jar"),
|
|
||||||
private val extraJvmArgs: Array<out String> = emptyArray(),
|
private val extraJvmArgs: Array<out String> = emptyArray(),
|
||||||
private val redirectConsoleTo: File? = null
|
private val redirectConsoleTo: File? = null
|
||||||
) {
|
) {
|
||||||
val cordaJar: Path by lazy {
|
val cordaJar: Path by lazy {
|
||||||
require(cordaJarUrl != null, { "corda.jar could not be found in classpath" })
|
val cordaJarUrl = requireNotNull(this::class.java.getResource("/corda.jar")) {
|
||||||
Paths.get(cordaJarUrl!!.toURI())
|
"corda.jar could not be found in classpath"
|
||||||
|
}
|
||||||
|
cordaJarUrl.toPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
@ -102,7 +99,7 @@ class NodeProcess(
|
|||||||
val nodeDir = baseDirectory(config).createDirectories()
|
val nodeDir = baseDirectory(config).createDirectories()
|
||||||
log.info("Node directory: {}", nodeDir)
|
log.info("Node directory: {}", nodeDir)
|
||||||
|
|
||||||
config.toText().byteInputStream().copyTo(nodeDir / "node.conf")
|
(nodeDir / "node.conf").writeText(config.toText())
|
||||||
defaultNetworkParameters.install(nodeDir)
|
defaultNetworkParameters.install(nodeDir)
|
||||||
|
|
||||||
val process = startNode(nodeDir)
|
val process = startNode(nodeDir)
|
||||||
|
@ -12,12 +12,12 @@ package net.corda.testing.common.internal
|
|||||||
|
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.isDirectory
|
import net.corda.core.internal.isDirectory
|
||||||
|
import net.corda.core.internal.toPath
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
|
||||||
|
|
||||||
object ProjectStructure {
|
object ProjectStructure {
|
||||||
val projectRootDir: Path = run {
|
val projectRootDir: Path = run {
|
||||||
var dir = Paths.get(javaClass.getResource("/").toURI())
|
var dir = javaClass.getResource("/").toPath()
|
||||||
while (!(dir / ".git").isDirectory()) {
|
while (!(dir / ".git").isDirectory()) {
|
||||||
dir = dir.parent
|
dir = dir.parent
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
package net.corda.testing.common.internal
|
package net.corda.testing.common.internal
|
||||||
|
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
|
import net.corda.core.internal.createFile
|
||||||
|
import net.corda.core.internal.deleteIfExists
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.nodeapi.internal.config.SSLConfiguration
|
import net.corda.nodeapi.internal.config.SSLConfiguration
|
||||||
import net.corda.nodeapi.internal.crypto.*
|
import net.corda.nodeapi.internal.crypto.*
|
||||||
@ -123,20 +125,19 @@ data class UnsafeKeyStore(private val delegate: KeyStore, val password: String)
|
|||||||
fun save(path: Path) = delegate.save(path, password)
|
fun save(path: Path) = delegate.save(path, password)
|
||||||
|
|
||||||
fun toTemporaryFile(fileName: String, fileExtension: String? = delegate.type.toLowerCase(), directory: Path): TemporaryFile {
|
fun toTemporaryFile(fileName: String, fileExtension: String? = delegate.type.toLowerCase(), directory: Path): TemporaryFile {
|
||||||
return TemporaryFile("$fileName.$fileExtension", directory).also { save(it.path) }
|
return TemporaryFile("$fileName.$fileExtension", directory).also { save(it.file) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TemporaryFile(fileName: String, val directory: Path) : AutoCloseable {
|
class TemporaryFile(fileName: String, val directory: Path) : AutoCloseable {
|
||||||
private val file = (directory / fileName).toFile()
|
val file: Path = (directory / fileName).createFile().toAbsolutePath()
|
||||||
init {
|
init {
|
||||||
file.createNewFile()
|
file.toFile().deleteOnExit()
|
||||||
file.deleteOnExit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val path: Path = file.toPath().toAbsolutePath()
|
override fun close() {
|
||||||
|
file.deleteIfExists()
|
||||||
override fun close() = FileUtils.forceDelete(file)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class UnsafeCertificate(val value: X509Certificate, val privateKey: PrivateKey?) {
|
data class UnsafeCertificate(val value: X509Certificate, val privateKey: PrivateKey?) {
|
||||||
@ -205,8 +206,8 @@ fun withKeyStores(server: KeyStores, client: KeyStores, action: (brokerSslOption
|
|||||||
action(serverSslConfiguration.value, clientSslConfiguration.value)
|
action(serverSslConfiguration.value, clientSslConfiguration.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FileUtils.deleteQuietly(clientDir.toFile())
|
clientDir.deleteIfExists()
|
||||||
FileUtils.deleteQuietly(serverDir.toFile())
|
serverDir.deleteIfExists()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun withCertificates(factoryDefaults: UnsafeCertificatesFactory.Defaults = UnsafeCertificatesFactory.defaults(), action: (server: KeyStores, client: KeyStores, createSelfSigned: (name: CordaX500Name) -> UnsafeCertificate, createSignedBy: (name: CordaX500Name, issuer: UnsafeCertificate) -> UnsafeCertificate) -> Unit) {
|
fun withCertificates(factoryDefaults: UnsafeCertificatesFactory.Defaults = UnsafeCertificatesFactory.defaults(), action: (server: KeyStores, client: KeyStores, createSelfSigned: (name: CordaX500Name) -> UnsafeCertificate, createSignedBy: (name: CordaX500Name, issuer: UnsafeCertificate) -> UnsafeCertificate) -> Unit) {
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
package net.corda.demobench.explorer
|
package net.corda.demobench.explorer
|
||||||
|
|
||||||
|
import net.corda.core.internal.copyTo
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.createDirectories
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.list
|
import net.corda.core.internal.list
|
||||||
@ -103,13 +104,13 @@ class Explorer internal constructor(private val explorerController: ExplorerCont
|
|||||||
Files.createSymbolicLink(destPath, path)
|
Files.createSymbolicLink(destPath, path)
|
||||||
} catch (e: UnsupportedOperationException) {
|
} catch (e: UnsupportedOperationException) {
|
||||||
// OS doesn't support symbolic links?
|
// OS doesn't support symbolic links?
|
||||||
Files.copy(path, destPath, REPLACE_EXISTING)
|
path.copyTo(destPath, REPLACE_EXISTING)
|
||||||
} catch (e: java.nio.file.FileAlreadyExistsException) {
|
} catch (e: java.nio.file.FileAlreadyExistsException) {
|
||||||
// OK, don't care ...
|
// OK, don't care ...
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
// Windows 10 might not allow this user to create a symlink
|
// Windows 10 might not allow this user to create a symlink
|
||||||
log.warn("Failed to create symlink '{}' for '{}': {}", destPath, path, e.message)
|
log.warn("Failed to create symlink '{}' for '{}': {}", destPath, path, e.message)
|
||||||
Files.copy(path, destPath, REPLACE_EXISTING)
|
path.copyTo(destPath, REPLACE_EXISTING)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
package net.corda.demobench.model
|
package net.corda.demobench.model
|
||||||
|
|
||||||
import com.typesafe.config.Config
|
import com.typesafe.config.Config
|
||||||
|
import net.corda.core.internal.deleteRecursively
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
import net.corda.nodeapi.internal.config.parseAs
|
import net.corda.nodeapi.internal.config.parseAs
|
||||||
@ -47,6 +48,6 @@ class InstallConfig internal constructor(val baseDir: Path, private val config:
|
|||||||
val key = config.key
|
val key = config.key
|
||||||
override val cordappsDir: Path = baseDir / "cordapps"
|
override val cordappsDir: Path = baseDir / "cordapps"
|
||||||
|
|
||||||
fun deleteBaseDir(): Boolean = baseDir.toFile().deleteRecursively()
|
fun deleteBaseDir(): Unit = baseDir.deleteRecursively()
|
||||||
fun installTo(installDir: Path) = config.copy(baseDir = installDir)
|
fun installTo(installDir: Path) = config.copy(baseDir = installDir)
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,10 @@ package net.corda.demobench.model
|
|||||||
import javafx.scene.control.Alert
|
import javafx.scene.control.Alert
|
||||||
import javafx.scene.control.Alert.AlertType.ERROR
|
import javafx.scene.control.Alert.AlertType.ERROR
|
||||||
import javafx.stage.Stage
|
import javafx.stage.Stage
|
||||||
|
import net.corda.core.internal.exists
|
||||||
|
import tornadofx.*
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import tornadofx.*
|
|
||||||
|
|
||||||
class JVMConfig : Controller() {
|
class JVMConfig : Controller() {
|
||||||
|
|
||||||
@ -45,17 +46,17 @@ class JVMConfig : Controller() {
|
|||||||
typealias atRuntime = (Path, String) -> Unit
|
typealias atRuntime = (Path, String) -> Unit
|
||||||
|
|
||||||
fun checkExists(path: Path, header: String) {
|
fun checkExists(path: Path, header: String) {
|
||||||
if (!path.toFile().exists()) {
|
if (path.exists()) return
|
||||||
val alert = Alert(ERROR)
|
|
||||||
alert.isResizable = true
|
|
||||||
alert.headerText = header
|
|
||||||
alert.contentText = "'$path' does not exist.\n" +
|
|
||||||
"Please install all of DemoBench's runtime dependencies or run the installer. " +
|
|
||||||
"See the documentation for more details."
|
|
||||||
|
|
||||||
val stage = alert.dialogPane.scene.window as Stage
|
val alert = Alert(ERROR)
|
||||||
stage.isAlwaysOnTop = true
|
alert.isResizable = true
|
||||||
|
alert.headerText = header
|
||||||
|
alert.contentText = "'$path' does not exist.\n" +
|
||||||
|
"Please install all of DemoBench's runtime dependencies or run the installer. " +
|
||||||
|
"See the documentation for more details."
|
||||||
|
|
||||||
alert.show()
|
val stage = alert.dialogPane.scene.window as Stage
|
||||||
}
|
stage.isAlwaysOnTop = true
|
||||||
|
|
||||||
|
alert.show()
|
||||||
}
|
}
|
||||||
|
@ -13,10 +13,7 @@ package net.corda.demobench.model
|
|||||||
import javafx.beans.binding.IntegerExpression
|
import javafx.beans.binding.IntegerExpression
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.copyToDirectory
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.createDirectories
|
|
||||||
import net.corda.core.internal.div
|
|
||||||
import net.corda.core.internal.noneOrSingle
|
|
||||||
import net.corda.core.node.NetworkParameters
|
import net.corda.core.node.NetworkParameters
|
||||||
import net.corda.core.node.NotaryInfo
|
import net.corda.core.node.NotaryInfo
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
@ -27,7 +24,6 @@ import net.corda.nodeapi.internal.network.NetworkParametersCopier
|
|||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.lang.management.ManagementFactory
|
import java.lang.management.ManagementFactory
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@ -131,11 +127,11 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() {
|
|||||||
|
|
||||||
// Write this node's configuration file into its working directory.
|
// Write this node's configuration file into its working directory.
|
||||||
val confFile = config.nodeDir / "node.conf"
|
val confFile = config.nodeDir / "node.conf"
|
||||||
Files.write(confFile, config.nodeConfig.toNodeConfText().toByteArray())
|
confFile.writeText(config.nodeConfig.toNodeConfText())
|
||||||
|
|
||||||
// Write this node's configuration file into its working directory.
|
// Write this node's configuration file into its working directory.
|
||||||
val webConfFile = config.nodeDir / "web-server.conf"
|
val webConfFile = config.nodeDir / "web-server.conf"
|
||||||
Files.write(webConfFile, config.nodeConfig.toWebServerConfText().toByteArray())
|
webConfFile.writeText(config.nodeConfig.toWebServerConfText())
|
||||||
|
|
||||||
// Execute the Corda node
|
// Execute the Corda node
|
||||||
val cordaEnv = System.getenv().toMutableMap().apply {
|
val cordaEnv = System.getenv().toMutableMap().apply {
|
||||||
@ -210,9 +206,7 @@ class NodeController(check: atRuntime = ::checkExists) : Controller() {
|
|||||||
log.info("Installed: $plugin")
|
log.info("Installed: $plugin")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!config.deleteBaseDir()) {
|
config.deleteBaseDir()
|
||||||
log.warning("Failed to remove '${config.baseDir}'")
|
|
||||||
}
|
|
||||||
|
|
||||||
return installed
|
return installed
|
||||||
}
|
}
|
||||||
|
@ -10,19 +10,16 @@
|
|||||||
|
|
||||||
package net.corda.demobench.plugin
|
package net.corda.demobench.plugin
|
||||||
|
|
||||||
import net.corda.core.internal.copyToDirectory
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.createDirectories
|
|
||||||
import net.corda.core.internal.exists
|
|
||||||
import net.corda.demobench.model.HasCordapps
|
import net.corda.demobench.model.HasCordapps
|
||||||
import net.corda.demobench.model.JVMConfig
|
import net.corda.demobench.model.JVMConfig
|
||||||
import net.corda.demobench.model.NodeConfig
|
import net.corda.demobench.model.NodeConfig
|
||||||
import net.corda.demobench.model.NodeConfigWrapper
|
import net.corda.demobench.model.NodeConfigWrapper
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.StandardCopyOption
|
import java.nio.file.StandardCopyOption
|
||||||
import java.util.stream.Stream
|
import kotlin.streams.toList
|
||||||
|
|
||||||
class CordappController : Controller() {
|
class CordappController : Controller() {
|
||||||
|
|
||||||
@ -54,18 +51,16 @@ class CordappController : Controller() {
|
|||||||
* Generates a stream of a node's non-built-in cordapps.
|
* Generates a stream of a node's non-built-in cordapps.
|
||||||
*/
|
*/
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun useCordappsFor(config: HasCordapps): Stream<Path> = walkCordapps(config.cordappsDir)
|
fun useCordappsFor(config: HasCordapps): List<Path> {
|
||||||
.filter { !bankOfCorda.endsWith(it.fileName) }
|
if (!config.cordappsDir.isDirectory()) return emptyList()
|
||||||
.filter { !finance.endsWith(it.fileName) }
|
return config.cordappsDir.walk(1) { paths -> paths
|
||||||
|
.filter(Path::isCordapp)
|
||||||
private fun walkCordapps(cordappsDir: Path): Stream<Path> {
|
.filter { !bankOfCorda.endsWith(it.fileName) }
|
||||||
return if (Files.isDirectory(cordappsDir))
|
.filter { !finance.endsWith(it.fileName) }
|
||||||
Files.walk(cordappsDir, 1).filter(Path::isCordapp)
|
.toList()
|
||||||
else
|
}
|
||||||
Stream.empty()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Path.isCordapp(): Boolean = Files.isReadable(this) && this.fileName.toString().endsWith(".jar")
|
fun Path.isCordapp(): Boolean = this.isReadable && this.fileName.toString().endsWith(".jar")
|
||||||
fun Path.inCordappsDir(): Boolean = (this.parent != null) && this.parent.endsWith("cordapps/")
|
fun Path.inCordappsDir(): Boolean = (this.parent != null) && this.parent.endsWith("cordapps/")
|
||||||
|
@ -14,8 +14,7 @@ import com.typesafe.config.Config
|
|||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import javafx.stage.FileChooser
|
import javafx.stage.FileChooser
|
||||||
import javafx.stage.FileChooser.ExtensionFilter
|
import javafx.stage.FileChooser.ExtensionFilter
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.div
|
|
||||||
import net.corda.demobench.model.*
|
import net.corda.demobench.model.*
|
||||||
import net.corda.demobench.plugin.CordappController
|
import net.corda.demobench.plugin.CordappController
|
||||||
import net.corda.demobench.plugin.inCordappsDir
|
import net.corda.demobench.plugin.inCordappsDir
|
||||||
@ -24,7 +23,6 @@ import tornadofx.*
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.nio.charset.StandardCharsets.UTF_8
|
|
||||||
import java.nio.file.FileSystems
|
import java.nio.file.FileSystems
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
@ -68,13 +66,13 @@ class ProfileController : Controller() {
|
|||||||
configs.forEach { config ->
|
configs.forEach { config ->
|
||||||
// Write the configuration file.
|
// Write the configuration file.
|
||||||
val nodeDir = fs.getPath(config.key).createDirectories()
|
val nodeDir = fs.getPath(config.key).createDirectories()
|
||||||
val file = Files.write(nodeDir / "node.conf", config.nodeConfig.serialiseAsString().toByteArray(UTF_8))
|
val file = (nodeDir / "node.conf").writeText(config.nodeConfig.serialiseAsString())
|
||||||
log.info("Wrote: $file")
|
log.info("Wrote: $file")
|
||||||
|
|
||||||
// Write all of the non-built-in cordapps.
|
// Write all of the non-built-in cordapps.
|
||||||
val cordappDir = Files.createDirectory(nodeDir.resolve(NodeConfig.cordappDirName))
|
val cordappDir = (nodeDir / NodeConfig.cordappDirName).createDirectory()
|
||||||
cordappController.useCordappsFor(config).forEach {
|
cordappController.useCordappsFor(config).forEach {
|
||||||
val cordapp = Files.copy(it, cordappDir.resolve(it.fileName.toString()))
|
val cordapp = it.copyToDirectory(cordappDir)
|
||||||
log.info("Wrote: $cordapp")
|
log.info("Wrote: $cordapp")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,8 +130,8 @@ class ProfileController : Controller() {
|
|||||||
val config = nodeIndex[cordapp.getName(0).toString()] ?: return@forEach
|
val config = nodeIndex[cordapp.getName(0).toString()] ?: return@forEach
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val cordappDir = Files.createDirectories(config.cordappsDir)
|
val cordappDir = config.cordappsDir.createDirectories()
|
||||||
Files.copy(cordapp, cordappDir.resolve(cordapp.fileName.toString()))
|
cordapp.copyToDirectory(cordappDir)
|
||||||
log.info("Loaded: $cordapp")
|
log.info("Loaded: $cordapp")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
log.log(Level.SEVERE, "Failed to extract '$cordapp': ${e.message}", e)
|
log.log(Level.SEVERE, "Failed to extract '$cordapp': ${e.message}", e)
|
||||||
@ -146,8 +144,5 @@ class ProfileController : Controller() {
|
|||||||
return configs
|
return configs
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parse(path: Path): Config = Files.newBufferedReader(path).use {
|
private fun parse(path: Path): Config = path.reader().use { ConfigFactory.parseReader(it) }
|
||||||
return ConfigFactory.parseReader(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ package net.corda.demobench.web
|
|||||||
import com.google.common.util.concurrent.RateLimiter
|
import com.google.common.util.concurrent.RateLimiter
|
||||||
import net.corda.core.concurrent.CordaFuture
|
import net.corda.core.concurrent.CordaFuture
|
||||||
import net.corda.core.internal.concurrent.openFuture
|
import net.corda.core.internal.concurrent.openFuture
|
||||||
|
import net.corda.core.internal.isDirectory
|
||||||
import net.corda.core.internal.until
|
import net.corda.core.internal.until
|
||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.core.utilities.minutes
|
import net.corda.core.utilities.minutes
|
||||||
@ -36,17 +37,17 @@ class WebServer internal constructor(private val webServerController: WebServerC
|
|||||||
|
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun open(config: NodeConfigWrapper): CordaFuture<URI> {
|
fun open(config: NodeConfigWrapper): CordaFuture<URI> {
|
||||||
val nodeDir = config.nodeDir.toFile()
|
val nodeDir = config.nodeDir
|
||||||
|
|
||||||
if (!nodeDir.isDirectory) {
|
if (!nodeDir.isDirectory()) {
|
||||||
log.warn("Working directory '{}' does not exist.", nodeDir.absolutePath)
|
log.warn("Working directory '{}' does not exist.", nodeDir.toAbsolutePath())
|
||||||
return openFuture()
|
return openFuture()
|
||||||
}
|
}
|
||||||
|
|
||||||
val legalName = config.nodeConfig.myLegalName
|
val legalName = config.nodeConfig.myLegalName
|
||||||
try {
|
try {
|
||||||
val p = webServerController.process()
|
val p = webServerController.process()
|
||||||
.directory(nodeDir)
|
.directory(nodeDir.toFile())
|
||||||
.start()
|
.start()
|
||||||
process = p
|
process = p
|
||||||
|
|
||||||
|
@ -11,30 +11,28 @@
|
|||||||
package net.corda.demobench.model
|
package net.corda.demobench.model
|
||||||
|
|
||||||
import com.jediterm.terminal.ui.UIUtil
|
import com.jediterm.terminal.ui.UIUtil
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
class JVMConfigTest {
|
class JVMConfigTest {
|
||||||
|
|
||||||
private val jvm = JVMConfig()
|
private val jvm = JVMConfig()
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test Java path`() {
|
fun `test Java path`() {
|
||||||
assertTrue(Files.isExecutable(jvm.javaPath.onFileSystem()))
|
assertThat(jvm.javaPath.onFileSystem()).isExecutable()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test application directory`() {
|
fun `test application directory`() {
|
||||||
assertTrue(Files.isDirectory(jvm.applicationDir))
|
assertThat(jvm.applicationDir).isDirectory()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test user home`() {
|
fun `test user home`() {
|
||||||
assertTrue(Files.isDirectory(jvm.userHome))
|
assertThat(jvm.userHome).isDirectory()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -51,8 +49,5 @@ class JVMConfigTest {
|
|||||||
assertEquals(listOf(java.toString(), "-jar", "testapp.jar", "arg1", "arg2", "arg3"), process.command())
|
assertEquals(listOf(java.toString(), "-jar", "testapp.jar", "arg1", "arg2", "arg3"), process.command())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Path.onFileSystem(): Path
|
private fun Path.onFileSystem(): Path = if (UIUtil.isWindows) parent.resolve(Paths.get("$fileName.exe")) else this
|
||||||
= if (UIUtil.isWindows) this.parent.resolve(Paths.get(this.fileName.toString() + ".exe"))
|
|
||||||
else this
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -14,12 +14,8 @@ import javafx.beans.InvalidationListener
|
|||||||
import javafx.beans.Observable
|
import javafx.beans.Observable
|
||||||
import javafx.beans.property.ObjectProperty
|
import javafx.beans.property.ObjectProperty
|
||||||
import javafx.beans.property.SimpleObjectProperty
|
import javafx.beans.property.SimpleObjectProperty
|
||||||
import net.corda.core.internal.createDirectories
|
import net.corda.core.internal.*
|
||||||
import net.corda.core.internal.div
|
|
||||||
import net.corda.core.internal.exists
|
|
||||||
import net.corda.core.internal.uncheckedCast
|
|
||||||
import tornadofx.*
|
import tornadofx.*
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -56,12 +52,12 @@ class SettingsModel(path: Path = Paths.get("conf")) : Component(), Observable {
|
|||||||
// Load config from properties file.
|
// Load config from properties file.
|
||||||
fun load() = config.apply {
|
fun load() = config.apply {
|
||||||
clear()
|
clear()
|
||||||
if (Files.exists(path)) Files.newInputStream(path).use { load(it) }
|
if (path.exists()) path.read { load(it) }
|
||||||
listeners.forEach { it.invalidated(this@SettingsModel) }
|
listeners.forEach { it.invalidated(this@SettingsModel) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save all changes in memory to properties file.
|
// Save all changes in memory to properties file.
|
||||||
fun commit() = Files.newOutputStream(path).use { config.store(it, "") }
|
fun commit() = path.write { config.store(it, "") }
|
||||||
|
|
||||||
private operator fun <T> Properties.getValue(receiver: Any, metadata: KProperty<*>): T {
|
private operator fun <T> Properties.getValue(receiver: Any, metadata: KProperty<*>): T {
|
||||||
return when (metadata.returnType.javaType) {
|
return when (metadata.returnType.javaType) {
|
||||||
|
@ -11,10 +11,10 @@
|
|||||||
package net.corda.explorer.model
|
package net.corda.explorer.model
|
||||||
|
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
|
import net.corda.core.internal.exists
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.rules.TemporaryFolder
|
import org.junit.rules.TemporaryFolder
|
||||||
import java.nio.file.Files
|
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFalse
|
import kotlin.test.assertFalse
|
||||||
import kotlin.test.assertTrue
|
import kotlin.test.assertTrue
|
||||||
@ -36,9 +36,9 @@ class SettingsModelTest {
|
|||||||
setting.portProperty.value = "100"
|
setting.portProperty.value = "100"
|
||||||
assertEquals("host", setting.hostProperty.value)
|
assertEquals("host", setting.hostProperty.value)
|
||||||
assertEquals("100", setting.portProperty.value)
|
assertEquals("100", setting.portProperty.value)
|
||||||
assertFalse(Files.exists(config))
|
assertFalse(config.exists())
|
||||||
setting.commit()
|
setting.commit()
|
||||||
assertTrue(Files.exists(config))
|
assertTrue(config.exists())
|
||||||
setting.hostProperty.value = "host2"
|
setting.hostProperty.value = "host2"
|
||||||
setting.portProperty.value = "200"
|
setting.portProperty.value = "200"
|
||||||
assertEquals("host2", setting.hostProperty.value)
|
assertEquals("host2", setting.hostProperty.value)
|
||||||
|
@ -118,7 +118,7 @@ object InteractiveShell {
|
|||||||
config["crash.auth"] = "corda"
|
config["crash.auth"] = "corda"
|
||||||
configuration.sshHostKeyDirectory?.apply {
|
configuration.sshHostKeyDirectory?.apply {
|
||||||
val sshKeysDir = configuration.sshHostKeyDirectory
|
val sshKeysDir = configuration.sshHostKeyDirectory
|
||||||
sshKeysDir.toFile().mkdirs()
|
sshKeysDir.createDirectories()
|
||||||
config["crash.ssh.keypath"] = (sshKeysDir / "hostkey.pem").toString()
|
config["crash.ssh.keypath"] = (sshKeysDir / "hostkey.pem").toString()
|
||||||
config["crash.ssh.keygen"] = "true"
|
config["crash.ssh.keygen"] = "true"
|
||||||
}
|
}
|
||||||
|
@ -9,11 +9,11 @@ import com.fasterxml.jackson.databind.SerializerProvider
|
|||||||
import com.google.common.io.Closeables
|
import com.google.common.io.Closeables
|
||||||
import net.corda.core.contracts.UniqueIdentifier
|
import net.corda.core.contracts.UniqueIdentifier
|
||||||
import net.corda.core.internal.copyTo
|
import net.corda.core.internal.copyTo
|
||||||
|
import net.corda.core.internal.inputStream
|
||||||
import org.crsh.command.InvocationContext
|
import org.crsh.command.InvocationContext
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import java.io.BufferedInputStream
|
import java.io.BufferedInputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ object InputStreamDeserializer : JsonDeserializer<InputStream>() {
|
|||||||
private val streams = Collections.synchronizedSet(HashSet<InputStream>())
|
private val streams = Collections.synchronizedSet(HashSet<InputStream>())
|
||||||
|
|
||||||
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): InputStream {
|
override fun deserialize(p: JsonParser, ctxt: DeserializationContext): InputStream {
|
||||||
val stream = object : BufferedInputStream(Files.newInputStream(Paths.get(p.text))) {
|
val stream = object : BufferedInputStream(Paths.get(p.text).inputStream()) {
|
||||||
override fun close() {
|
override fun close() {
|
||||||
super.close()
|
super.close()
|
||||||
streams.remove(this)
|
streams.remove(this)
|
||||||
|
@ -10,20 +10,19 @@
|
|||||||
|
|
||||||
package net.corda.tools.shell
|
package net.corda.tools.shell
|
||||||
|
|
||||||
|
import net.corda.core.internal.toPath
|
||||||
import net.corda.core.utilities.NetworkHostAndPort
|
import net.corda.core.utilities.NetworkHostAndPort
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.slf4j.event.Level
|
import org.slf4j.event.Level
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class StandaloneShellArgsParserTest {
|
class StandaloneShellArgsParserTest {
|
||||||
|
private val CONFIG_FILE = StandaloneShellArgsParserTest::class.java.getResource("/config.conf").toPath()
|
||||||
private val CONFIG_FILE = File(StandaloneShellArgsParserTest::class.java.getResource("/config.conf").toURI())
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun args_to_cmd_options() {
|
fun args_to_cmd_options() {
|
||||||
|
|
||||||
val args = arrayOf("--config-file", "/x/y/z/config.conf",
|
val args = arrayOf("--config-file", "/x/y/z/config.conf",
|
||||||
"--commands-directory", "/x/y/commands",
|
"--commands-directory", "/x/y/commands",
|
||||||
"--cordpass-directory", "/x/y/cordapps",
|
"--cordpass-directory", "/x/y/cordapps",
|
||||||
@ -42,7 +41,8 @@ class StandaloneShellArgsParserTest {
|
|||||||
"--truststore-type", "dummy",
|
"--truststore-type", "dummy",
|
||||||
"--keystore-type", "JKS")
|
"--keystore-type", "JKS")
|
||||||
|
|
||||||
val expectedOptions = CommandLineOptions(configFile = "/x/y/z/config.conf",
|
val expectedOptions = CommandLineOptions(
|
||||||
|
configFile = "/x/y/z/config.conf",
|
||||||
commandsDirectory = Paths.get("/x/y/commands").normalize().toAbsolutePath(),
|
commandsDirectory = Paths.get("/x/y/commands").normalize().toAbsolutePath(),
|
||||||
cordappsDirectory = Paths.get("/x/y/cordapps").normalize().toAbsolutePath(),
|
cordappsDirectory = Paths.get("/x/y/cordapps").normalize().toAbsolutePath(),
|
||||||
host = "alocalhost",
|
host = "alocalhost",
|
||||||
@ -62,7 +62,7 @@ class StandaloneShellArgsParserTest {
|
|||||||
|
|
||||||
val options = CommandLineOptionParser().parse(*args)
|
val options = CommandLineOptionParser().parse(*args)
|
||||||
|
|
||||||
assertEquals(expectedOptions, options)
|
assertThat(options).isEqualTo(expectedOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -137,7 +137,7 @@ class StandaloneShellArgsParserTest {
|
|||||||
@Test
|
@Test
|
||||||
fun cmd_options_to_config_from_file() {
|
fun cmd_options_to_config_from_file() {
|
||||||
|
|
||||||
val options = CommandLineOptions(configFile = CONFIG_FILE.absolutePath,
|
val options = CommandLineOptions(configFile = CONFIG_FILE.toString(),
|
||||||
commandsDirectory = null,
|
commandsDirectory = null,
|
||||||
cordappsDirectory = null,
|
cordappsDirectory = null,
|
||||||
host = null,
|
host = null,
|
||||||
@ -176,7 +176,7 @@ class StandaloneShellArgsParserTest {
|
|||||||
@Test
|
@Test
|
||||||
fun cmd_options_override_config_from_file() {
|
fun cmd_options_override_config_from_file() {
|
||||||
|
|
||||||
val options = CommandLineOptions(configFile = CONFIG_FILE.absolutePath,
|
val options = CommandLineOptions(configFile = CONFIG_FILE.toString(),
|
||||||
commandsDirectory = null,
|
commandsDirectory = null,
|
||||||
cordappsDirectory = null,
|
cordappsDirectory = null,
|
||||||
host = null,
|
host = null,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user