From 407b467f671122de7bafef08a2c75aab7908c3f6 Mon Sep 17 00:00:00 2001 From: Shams Asari Date: Mon, 24 Jul 2017 10:12:27 +0100 Subject: [PATCH] Moved the majority of the contents of Utils.kt into either InternalUtils.kt or KotlinUtils.kt. What remains is being dealt with in another PR. --- .../corda/client/jfx/NodeMonitorModelTest.kt | 2 +- .../corda/client/rpc/internal/RPCClient.kt | 2 +- .../kotlin/rpc/StandaloneCordaRPClientTest.kt | 2 +- .../src/main/kotlin/net/corda/core/Streams.kt | 30 --- core/src/main/kotlin/net/corda/core/Utils.kt | 202 +----------------- .../kotlin/net/corda/core/contracts/Amount.kt | 11 +- .../core/crypto/composite/CompositeKey.kt | 3 +- .../kotlin/net/corda/core/flows/FlowLogic.kt | 2 +- .../core/flows/ResolveTransactionsFlow.kt | 4 +- .../net/corda/core/internal/InternalUtils.kt | 170 +++++++++++++++ .../core/node/services/NetworkMapCache.kt | 7 +- .../core/serialization/amqp/MapSerializer.kt | 13 +- .../serialization/amqp/SerializerFactory.kt | 1 - .../core/transactions/BaseTransaction.kt | 2 +- .../net/corda/core/utilities/KotlinUtils.kt | 11 +- .../corda/core/CollectionExtensionTests.kt | 40 ---- .../test/kotlin/net/corda/core/StreamsTest.kt | 42 ---- .../core/crypto/X509NameConstraintsTest.kt | 2 +- .../corda/core/crypto/X509UtilitiesTest.kt | 2 +- .../corda/core/internal/InternalUtilsTest.kt | 90 ++++++++ .../amqp/SerializationOutputTests.kt | 2 +- docs/source/api-index.rst | 11 +- docs/source/changelog.rst | 3 + .../kotlin/net/corda/nodeapi/RPCStructures.kt | 7 +- .../corda/nodeapi/config/ConfigUtilities.kt | 2 +- .../node/services/DistributedServiceTests.kt | 2 +- .../statemachine/LargeTransactionsTest.kt | 2 +- .../services/messaging/P2PMessagingTest.kt | 2 +- .../net/corda/node/internal/NodeStartup.kt | 4 +- .../messaging/ArtemisMessagingServer.kt | 1 + .../network/InMemoryNetworkMapCache.kt | 2 +- .../DBTransactionMappingStorage.kt | 2 +- .../persistence/DBTransactionStorage.kt | 2 +- ...achineRecordedTransactionMappingStorage.kt | 2 +- .../statemachine/FlowStateMachineImpl.kt | 4 +- .../statemachine/StateMachineManager.kt | 2 +- .../node/services/transactions/BFTSMaRt.kt | 2 +- .../services/vault/HibernateVaultQueryImpl.kt | 2 +- .../node/services/vault/NodeVaultService.kt | 4 +- .../net/corda/node/shell/InteractiveShell.kt | 5 +- .../node/messaging/TwoPartyTradeFlowTests.kt | 3 +- .../corda/node/utilities/ObservablesTests.kt | 4 +- .../NetworkisRegistrationHelperTest.kt | 2 +- .../corda/attachmentdemo/AttachmentDemo.kt | 2 +- .../corda/irs/api/NodeInterestRatesTest.kt | 9 +- .../net/corda/notarydemo/BFTNotaryCordform.kt | 4 +- .../net/corda/vega/portfolio/Portfolio.kt | 5 +- .../net/corda/testing/node/TestClock.kt | 1 + .../kotlin/net/corda/webserver/WebServer.kt | 2 +- 49 files changed, 353 insertions(+), 380 deletions(-) delete mode 100644 core/src/main/kotlin/net/corda/core/Streams.kt delete mode 100644 core/src/test/kotlin/net/corda/core/CollectionExtensionTests.kt delete mode 100644 core/src/test/kotlin/net/corda/core/StreamsTest.kt create mode 100644 core/src/test/kotlin/net/corda/core/internal/InternalUtilsTest.kt diff --git a/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt b/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt index 29617faad5..4b394bf2a4 100644 --- a/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt +++ b/client/jfx/src/integration-test/kotlin/net/corda/client/jfx/NodeMonitorModelTest.kt @@ -2,7 +2,7 @@ package net.corda.client.jfx import net.corda.client.jfx.model.NodeMonitorModel import net.corda.client.jfx.model.ProgressTrackingEvent -import net.corda.core.bufferUntilSubscribed +import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.contracts.Amount import net.corda.core.contracts.DOLLARS import net.corda.core.contracts.USD diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt index 54a9964d92..94fa65a018 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/RPCClient.kt @@ -1,7 +1,7 @@ package net.corda.client.rpc.internal import net.corda.core.crypto.random63BitValue -import net.corda.core.logElapsedTime +import net.corda.core.internal.logElapsedTime import net.corda.core.messaging.RPCOps import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationDefaults diff --git a/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt b/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt index b8dfe87614..15979bf8df 100644 --- a/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt +++ b/client/rpc/src/smoke-test/kotlin/net/corda/kotlin/rpc/StandaloneCordaRPClientTest.kt @@ -5,7 +5,7 @@ import com.google.common.hash.HashingInputStream import net.corda.client.rpc.CordaRPCConnection import net.corda.client.rpc.notUsed import net.corda.contracts.asset.Cash -import net.corda.core.InputStreamAndHash +import net.corda.core.internal.InputStreamAndHash import net.corda.core.contracts.* import net.corda.core.crypto.SecureHash import net.corda.core.getOrThrow diff --git a/core/src/main/kotlin/net/corda/core/Streams.kt b/core/src/main/kotlin/net/corda/core/Streams.kt deleted file mode 100644 index 2f33522c35..0000000000 --- a/core/src/main/kotlin/net/corda/core/Streams.kt +++ /dev/null @@ -1,30 +0,0 @@ -package net.corda.core - -import java.util.* -import java.util.Spliterator.* -import java.util.stream.IntStream -import java.util.stream.Stream -import java.util.stream.StreamSupport -import kotlin.streams.asSequence - -private fun IntProgression.spliteratorOfInt(): Spliterator.OfInt { - val kotlinIterator = iterator() - val javaIterator = object : PrimitiveIterator.OfInt { - override fun nextInt() = kotlinIterator.nextInt() - override fun hasNext() = kotlinIterator.hasNext() - override fun remove() = throw UnsupportedOperationException("remove") - } - val spliterator = Spliterators.spliterator( - javaIterator, - (1 + (last - first) / step).toLong(), - SUBSIZED or IMMUTABLE or NONNULL or SIZED or ORDERED or SORTED or DISTINCT - ) - return if (step > 0) spliterator else object : Spliterator.OfInt by spliterator { - override fun getComparator() = Comparator.reverseOrder() - } -} - -fun IntProgression.stream(): IntStream = StreamSupport.intStream(spliteratorOfInt(), false) - -@Suppress("UNCHECKED_CAST") // When toArray has filled in the array, the component type is no longer T? but T (that may itself be nullable). -inline fun Stream.toTypedArray() = toArray { size -> arrayOfNulls(size) } as Array diff --git a/core/src/main/kotlin/net/corda/core/Utils.kt b/core/src/main/kotlin/net/corda/core/Utils.kt index 11121de66c..9089a0c18f 100644 --- a/core/src/main/kotlin/net/corda/core/Utils.kt +++ b/core/src/main/kotlin/net/corda/core/Utils.kt @@ -1,49 +1,18 @@ -// TODO Move out the Kotlin specific stuff into a separate file @file:JvmName("Utils") package net.corda.core -import com.google.common.base.Throwables -import com.google.common.io.ByteStreams import com.google.common.util.concurrent.* -import net.corda.core.crypto.SecureHash -import net.corda.core.crypto.sha256 -import net.corda.core.internal.createDirectories -import net.corda.core.internal.div -import net.corda.core.internal.write import org.slf4j.Logger import rx.Observable import rx.Observer -import rx.subjects.PublishSubject -import rx.subjects.UnicastSubject -import java.io.* -import java.math.BigDecimal -import java.nio.file.Files -import java.nio.file.Path import java.time.Duration import java.util.concurrent.CompletableFuture import java.util.concurrent.ExecutionException import java.util.concurrent.Future import java.util.concurrent.TimeUnit -import java.util.zip.Deflater -import java.util.zip.ZipEntry -import java.util.zip.ZipInputStream -import java.util.zip.ZipOutputStream -// TODO: Review by EOY2016 if we ever found these utilities helpful. -val Int.bd: BigDecimal get() = BigDecimal(this) -val Double.bd: BigDecimal get() = BigDecimal(this) -val String.bd: BigDecimal get() = BigDecimal(this) -val Long.bd: BigDecimal get() = BigDecimal(this) - -fun String.abbreviate(maxWidth: Int): String = if (length <= maxWidth) this else take(maxWidth - 1) + "…" - -/** Like the + operator but throws an exception in case of integer overflow. */ -infix fun Int.checkedAdd(b: Int) = Math.addExact(this, b) - -/** Like the + operator but throws an exception in case of integer overflow. */ -@Suppress("unused") -infix fun Long.checkedAdd(b: Long) = Math.addExact(this, b) +// TODO Delete this file once the Future stuff is out of here /** Same as [Future.get] but with a more descriptive name, and doesn't throw [ExecutionException], instead throwing its cause */ fun Future.getOrThrow(timeout: Duration? = null): T { @@ -92,163 +61,6 @@ fun ListenableFuture.toObservable(): Observable { } } -/** Returns the index of the given item or throws [IllegalArgumentException] if not found. */ -fun List.indexOfOrThrow(item: T): Int { - val i = indexOf(item) - require(i != -1) - return i -} - -/** - * Returns the single element matching the given [predicate], or `null` if element was not found, - * or throws if more than one element was found. - */ -fun Iterable.noneOrSingle(predicate: (T) -> Boolean): T? { - var single: T? = null - for (element in this) { - if (predicate(element)) { - if (single == null) { - single = element - } else throw IllegalArgumentException("Collection contains more than one matching element.") - } - } - return single -} - -/** Returns single element, or `null` if element was not found, or throws if more than one element was found. */ -fun Iterable.noneOrSingle(): T? { - var single: T? = null - for (element in this) { - if (single == null) { - single = element - } else throw IllegalArgumentException("Collection contains more than one matching element.") - } - return single -} - -/** Returns a random element in the list, or null if empty */ -fun List.randomOrNull(): T? { - if (size <= 1) return firstOrNull() - val randomIndex = (Math.random() * size).toInt() - return get(randomIndex) -} - -/** Returns a random element in the list matching the given predicate, or null if none found */ -fun List.randomOrNull(predicate: (T) -> Boolean) = filter(predicate).randomOrNull() - -inline fun elapsedTime(block: () -> Unit): Duration { - val start = System.nanoTime() - block() - val end = System.nanoTime() - return Duration.ofNanos(end - start) -} - -// TODO: Add inline back when a new Kotlin version is released and check if the java.lang.VerifyError -// returns in the IRSSimulationTest. If not, commit the inline back. -fun logElapsedTime(label: String, logger: Logger? = null, body: () -> T): T { - // Use nanoTime as it's monotonic. - val now = System.nanoTime() - try { - return body() - } finally { - val elapsed = Duration.ofNanos(System.nanoTime() - now).toMillis() - if (logger != null) - logger.info("$label took $elapsed msec") - else - println("$label took $elapsed msec") - } -} - -fun Logger.logElapsedTime(label: String, body: () -> T): T = logElapsedTime(label, this, body) - -/** - * Given a path to a zip file, extracts it to the given directory. - */ -fun extractZipFile(zipFile: Path, toDirectory: Path) = extractZipFile(Files.newInputStream(zipFile), toDirectory) - -/** - * Given a zip file input stream, extracts it to the given directory. - */ -fun extractZipFile(inputStream: InputStream, toDirectory: Path) { - val normalisedDirectory = toDirectory.normalize().createDirectories() - ZipInputStream(BufferedInputStream(inputStream)).use { - while (true) { - val e = it.nextEntry ?: break - val outPath = (normalisedDirectory / e.name).normalize() - - // Security checks: we should reject a zip that contains tricksy paths that try to escape toDirectory. - check(outPath.startsWith(normalisedDirectory)) { "ZIP contained a path that resolved incorrectly: ${e.name}" } - - if (e.isDirectory) { - outPath.createDirectories() - continue - } - outPath.write { out -> - ByteStreams.copy(it, out) - } - it.closeEntry() - } - } -} - -/** Convert a [ByteArrayOutputStream] to [InputStreamAndHash]. */ -fun ByteArrayOutputStream.getInputStreamAndHash(baos: ByteArrayOutputStream): InputStreamAndHash { - val bytes = baos.toByteArray() - return InputStreamAndHash(ByteArrayInputStream(bytes), bytes.sha256()) -} - -data class InputStreamAndHash(val inputStream: InputStream, val sha256: SecureHash.SHA256) { - companion object { - /** - * Get a valid InputStream from an in-memory zip as required for some tests. The zip consists of a single file - * called "z" that contains the given content byte repeated the given number of times. - * Note that a slightly bigger than numOfExpectedBytes size is expected. - */ - @Throws(IllegalArgumentException::class) - @JvmStatic - fun createInMemoryTestZip(numOfExpectedBytes: Int, content: Byte): InputStreamAndHash { - require(numOfExpectedBytes > 0) - val baos = ByteArrayOutputStream() - ZipOutputStream(baos).use { zos -> - val arraySize = 1024 - val bytes = ByteArray(arraySize) { content } - val n = (numOfExpectedBytes - 1) / arraySize + 1 // same as Math.ceil(numOfExpectedBytes/arraySize). - zos.setLevel(Deflater.NO_COMPRESSION) - zos.putNextEntry(ZipEntry("z")) - for (i in 0 until n) { - zos.write(bytes, 0, arraySize) - } - zos.closeEntry() - } - return baos.getInputStreamAndHash(baos) - } - } -} - -// TODO: Generic csv printing utility for clases. - -val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this) - -/** - * Returns an Observable that buffers events until subscribed. - * @see UnicastSubject - */ -fun Observable.bufferUntilSubscribed(): Observable { - val subject = UnicastSubject.create() - val subscription = subscribe(subject) - return subject.doOnUnsubscribe { subscription.unsubscribe() } -} - -/** - * Copy an [Observer] to multiple other [Observer]s. - */ -fun Observer.tee(vararg teeTo: Observer): Observer { - val subject = PublishSubject.create() - subject.subscribe(this) - teeTo.forEach { subject.subscribe(it) } - return subject -} - /** * Returns a [ListenableFuture] bound to the *first* item emitted by this Observable. The future will complete with a * NoSuchElementException if no items are emitted or any other error thrown by the Observable. If it's cancelled then @@ -273,15 +85,3 @@ private class ObservableToFuture(observable: Observable) : AbstractFuture< override fun onCompleted() {} } - -/** Return the sum of an Iterable of [BigDecimal]s. */ -fun Iterable.sum(): BigDecimal = fold(BigDecimal.ZERO) { a, b -> a + b } - -fun Class.checkNotUnorderedHashMap() { - if (HashMap::class.java.isAssignableFrom(this) && !LinkedHashMap::class.java.isAssignableFrom(this)) { - throw NotSerializableException("Map type $this is unstable under iteration. Suggested fix: use LinkedHashMap instead.") - } -} - -fun Class<*>.requireExternal(msg: String = "Internal class") - = require(!name.startsWith("net.corda.node.") && !name.contains(".internal.")) { "$msg: $name" } diff --git a/core/src/main/kotlin/net/corda/core/contracts/Amount.kt b/core/src/main/kotlin/net/corda/core/contracts/Amount.kt index 0569c6751c..e8d3982c2f 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/Amount.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/Amount.kt @@ -1,5 +1,8 @@ package net.corda.core.contracts +import net.corda.core.crypto.composite.CompositeKey +import net.corda.core.utilities.exactAdd +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import java.math.BigDecimal import java.math.RoundingMode @@ -168,7 +171,7 @@ data class Amount(val quantity: Long, val displayTokenSize: BigDecimal, */ operator fun plus(other: Amount): Amount { checkToken(other) - return Amount(Math.addExact(quantity, other.quantity), displayTokenSize, token) + return Amount(quantity exactAdd other.quantity, displayTokenSize, token) } /** @@ -268,9 +271,9 @@ data class SourceAndAmount(val source: P, val amount: Amou * but in various scenarios it may be more consistent to allow positive and negative values. * For example it is common for a bank to code asset flows as gains and losses from its perspective i.e. always the destination. * @param token represents the type of asset token as would be used to construct Amount objects. - * @param source is the [Party], [Account], [CompositeKey], or other identifier of the token source if quantityDelta is positive, + * @param source is the [Party], [CompositeKey], or other identifier of the token source if quantityDelta is positive, * or the token sink if quantityDelta is negative. The type P should support value equality. - * @param destination is the [Party], [Account], [CompositeKey], or other identifier of the token sink if quantityDelta is positive, + * @param destination is the [Party], [CompositeKey], or other identifier of the token sink if quantityDelta is positive, * or the token source if quantityDelta is negative. The type P should support value equality. */ @CordaSerializable @@ -329,7 +332,7 @@ class AmountTransfer(val quantityDelta: Long, "Only AmountTransfer between the same two parties can be aggregated/netted" } return if (other.source == source) { - AmountTransfer(Math.addExact(quantityDelta, other.quantityDelta), token, source, destination) + AmountTransfer(quantityDelta exactAdd other.quantityDelta, token, source, destination) } else { AmountTransfer(Math.subtractExact(quantityDelta, other.quantityDelta), token, source, destination) } diff --git a/core/src/main/kotlin/net/corda/core/crypto/composite/CompositeKey.kt b/core/src/main/kotlin/net/corda/core/crypto/composite/CompositeKey.kt index 56035333bb..f9ca0dad7c 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/composite/CompositeKey.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/composite/CompositeKey.kt @@ -5,6 +5,7 @@ import net.corda.core.crypto.composite.CompositeKey.NodeAndWeight import net.corda.core.crypto.keys import net.corda.core.crypto.provider.CordaObjectIdentifier import net.corda.core.crypto.toStringShort +import net.corda.core.utilities.exactAdd import net.corda.core.serialization.CordaSerializable import net.corda.core.utilities.sequence import org.bouncycastle.asn1.* @@ -126,7 +127,7 @@ class CompositeKey private constructor(val threshold: Int, children: List 0) { "Non-positive weight: $weight detected." } - sum = Math.addExact(sum, weight) // Add and check for integer overflow. + sum = sum exactAdd weight // Add and check for integer overflow. } return sum } diff --git a/core/src/main/kotlin/net/corda/core/flows/FlowLogic.kt b/core/src/main/kotlin/net/corda/core/flows/FlowLogic.kt index 3490441af3..ffcc9af808 100644 --- a/core/src/main/kotlin/net/corda/core/flows/FlowLogic.kt +++ b/core/src/main/kotlin/net/corda/core/flows/FlowLogic.kt @@ -1,10 +1,10 @@ package net.corda.core.flows import co.paralleluniverse.fibers.Suspendable -import net.corda.core.abbreviate import net.corda.core.crypto.SecureHash import net.corda.core.identity.Party import net.corda.core.internal.FlowStateMachine +import net.corda.core.internal.abbreviate import net.corda.core.messaging.DataFeed import net.corda.core.node.ServiceHub import net.corda.core.transactions.SignedTransaction diff --git a/core/src/main/kotlin/net/corda/core/flows/ResolveTransactionsFlow.kt b/core/src/main/kotlin/net/corda/core/flows/ResolveTransactionsFlow.kt index 325802548c..1164d075ba 100644 --- a/core/src/main/kotlin/net/corda/core/flows/ResolveTransactionsFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/ResolveTransactionsFlow.kt @@ -1,7 +1,7 @@ package net.corda.core.flows import co.paralleluniverse.fibers.Suspendable -import net.corda.core.checkedAdd +import net.corda.core.utilities.exactAdd import net.corda.core.crypto.SecureHash import net.corda.core.getOrThrow import net.corda.core.identity.Party @@ -176,7 +176,7 @@ class ResolveTransactionsFlow(private val txHashes: Set, val inputHashes = downloads.flatMap { it.tx.inputs }.map { it.txhash } nextRequests.addAll(inputHashes) - limitCounter = limitCounter checkedAdd nextRequests.size + limitCounter = limitCounter exactAdd nextRequests.size if (limitCounter > limit) throw ExcessivelyLargeTransactionGraph() } diff --git a/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt b/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt index 9db156bcee..0e70327c02 100644 --- a/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt +++ b/core/src/main/kotlin/net/corda/core/internal/InternalUtils.kt @@ -1,17 +1,37 @@ package net.corda.core.internal +import com.google.common.base.Throwables +import net.corda.core.crypto.SecureHash +import net.corda.core.crypto.sha256 +import org.slf4j.Logger +import rx.Observable +import rx.Observer +import rx.subjects.PublishSubject +import rx.subjects.UnicastSubject +import java.io.ByteArrayInputStream +import java.io.ByteArrayOutputStream import java.io.InputStream import java.io.OutputStream import java.lang.reflect.Field +import java.math.BigDecimal import java.nio.charset.Charset import java.nio.charset.StandardCharsets.UTF_8 import java.nio.file.* import java.nio.file.attribute.FileAttribute import java.time.Duration import java.time.temporal.Temporal +import java.util.* +import java.util.Spliterator.* +import java.util.stream.IntStream import java.util.stream.Stream +import java.util.stream.StreamSupport +import java.util.zip.Deflater +import java.util.zip.ZipEntry +import java.util.zip.ZipOutputStream import kotlin.reflect.KClass +inline val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this) + infix fun Temporal.until(endExclusive: Temporal): Duration = Duration.between(this, endExclusive) operator fun Duration.div(divider: Long): Duration = dividedBy(divider) @@ -24,6 +44,50 @@ operator fun Duration.times(multiplicand: Long): Duration = multipliedBy(multipl 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 + * if more than one element was found. + */ +inline fun Iterable.noneOrSingle(predicate: (T) -> Boolean): T? { + val iterator = iterator() + for (single in iterator) { + if (predicate(single)) { + while (iterator.hasNext()) { + if (predicate(iterator.next())) throw IllegalArgumentException("Collection contains more than one matching element.") + } + return single + } + } + return null +} + +/** + * Returns the single element, or `null` if the list is empty, or throws an exception if it has more than one element. + */ +fun List.noneOrSingle(): T? { + return when (size) { + 0 -> null + 1 -> this[0] + else -> throw IllegalArgumentException("List has more than one element.") + } +} + +/** Returns a random element in the list, or `null` if empty */ +fun List.randomOrNull(): T? { + return when (size) { + 0 -> null + 1 -> this[0] + else -> this[(Math.random() * size).toInt()] + } +} + +/** Returns the index of the given item or throws [IllegalArgumentException] if not found. */ +fun List.indexOfOrThrow(item: T): Int { + val i = indexOf(item) + require(i != -1) + 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) @@ -54,6 +118,112 @@ fun Path.writeLines(lines: Iterable, charset: Charset = UTF_8, var fun InputStream.copyTo(target: Path, vararg options: CopyOption): Long = Files.copy(this, target, *options) +fun String.abbreviate(maxWidth: Int): String = if (length <= maxWidth) this else take(maxWidth - 1) + "…" + +/** Return the sum of an Iterable of [BigDecimal]s. */ +fun Iterable.sum(): BigDecimal = fold(BigDecimal.ZERO) { a, b -> a + b } + +/** + * Returns an Observable that buffers events until subscribed. + * @see UnicastSubject + */ +fun Observable.bufferUntilSubscribed(): Observable { + val subject = UnicastSubject.create() + val subscription = subscribe(subject) + return subject.doOnUnsubscribe { subscription.unsubscribe() } +} + +/** Copy an [Observer] to multiple other [Observer]s. */ +fun Observer.tee(vararg teeTo: Observer): Observer { + val subject = PublishSubject.create() + subject.subscribe(this) + teeTo.forEach { subject.subscribe(it) } + return subject +} + +/** Executes the given code block and returns a [Duration] of how long it took to execute in nanosecond precision. */ +inline fun elapsedTime(block: () -> Unit): Duration { + val start = System.nanoTime() + block() + val end = System.nanoTime() + return Duration.ofNanos(end - start) +} + + +fun Logger.logElapsedTime(label: String, body: () -> T): T = logElapsedTime(label, this, body) + +// TODO: Add inline back when a new Kotlin version is released and check if the java.lang.VerifyError +// returns in the IRSSimulationTest. If not, commit the inline back. +fun logElapsedTime(label: String, logger: Logger? = null, body: () -> T): T { + // Use nanoTime as it's monotonic. + val now = System.nanoTime() + try { + return body() + } finally { + val elapsed = Duration.ofNanos(System.nanoTime() - now).toMillis() + if (logger != null) + logger.info("$label took $elapsed msec") + else + println("$label took $elapsed msec") + } +} + +/** Convert a [ByteArrayOutputStream] to [InputStreamAndHash]. */ +fun ByteArrayOutputStream.toInputStreamAndHash(): InputStreamAndHash { + val bytes = toByteArray() + return InputStreamAndHash(ByteArrayInputStream(bytes), bytes.sha256()) +} + +data class InputStreamAndHash(val inputStream: InputStream, val sha256: SecureHash.SHA256) { + companion object { + /** + * Get a valid InputStream from an in-memory zip as required for some tests. The zip consists of a single file + * called "z" that contains the given content byte repeated the given number of times. + * Note that a slightly bigger than numOfExpectedBytes size is expected. + */ + fun createInMemoryTestZip(numOfExpectedBytes: Int, content: Byte): InputStreamAndHash { + require(numOfExpectedBytes > 0) + val baos = ByteArrayOutputStream() + ZipOutputStream(baos).use { zos -> + val arraySize = 1024 + val bytes = ByteArray(arraySize) { content } + val n = (numOfExpectedBytes - 1) / arraySize + 1 // same as Math.ceil(numOfExpectedBytes/arraySize). + zos.setLevel(Deflater.NO_COMPRESSION) + zos.putNextEntry(ZipEntry("z")) + for (i in 0 until n) { + zos.write(bytes, 0, arraySize) + } + zos.closeEntry() + } + return baos.toInputStreamAndHash() + } + } +} + +fun IntIterator.toJavaIterator(): PrimitiveIterator.OfInt { + return object : PrimitiveIterator.OfInt { + override fun nextInt() = this@toJavaIterator.nextInt() + override fun hasNext() = this@toJavaIterator.hasNext() + override fun remove() = throw UnsupportedOperationException("remove") + } +} + +private fun IntProgression.toSpliterator(): Spliterator.OfInt { + val spliterator = Spliterators.spliterator( + iterator().toJavaIterator(), + (1 + (last - first) / step).toLong(), + SUBSIZED or IMMUTABLE or NONNULL or SIZED or ORDERED or SORTED or DISTINCT + ) + return if (step > 0) spliterator else object : Spliterator.OfInt by spliterator { + override fun getComparator() = Comparator.reverseOrder() + } +} + +fun IntProgression.stream(parallel: Boolean = false): IntStream = StreamSupport.intStream(toSpliterator(), parallel) + +@Suppress("UNCHECKED_CAST") // When toArray has filled in the array, the component type is no longer T? but T (that may itself be nullable). +inline fun Stream.toTypedArray() = toArray { size -> arrayOfNulls(size) } as Array + fun Class.castIfPossible(obj: Any): T? = if (isInstance(obj)) cast(obj) else null /** Returns a [DeclaredField] wrapper around the declared (possibly non-public) static field of the receiver [Class]. */ diff --git a/core/src/main/kotlin/net/corda/core/node/services/NetworkMapCache.kt b/core/src/main/kotlin/net/corda/core/node/services/NetworkMapCache.kt index cda2fc7c5f..a651790053 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/NetworkMapCache.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/NetworkMapCache.kt @@ -6,8 +6,7 @@ import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.messaging.DataFeed import net.corda.core.node.NodeInfo -import net.corda.core.node.ServiceHub -import net.corda.core.randomOrNull +import net.corda.core.internal.randomOrNull import net.corda.core.serialization.CordaSerializable import org.bouncycastle.asn1.x500.X500Name import rx.Observable @@ -98,9 +97,9 @@ interface NetworkMapCache { /** Gets a notary identity by the given name. */ fun getNotary(principal: X500Name): Party? { - val notaryNode = notaryNodes.randomOrNull { + val notaryNode = notaryNodes.filter { it.advertisedServices.any { it.info.type.isSubTypeOf(ServiceType.notary) && it.info.name == principal } - } + }.randomOrNull() return notaryNode?.notaryIdentity } diff --git a/core/src/main/kotlin/net/corda/core/serialization/amqp/MapSerializer.kt b/core/src/main/kotlin/net/corda/core/serialization/amqp/MapSerializer.kt index 95803f3070..559ecd0248 100644 --- a/core/src/main/kotlin/net/corda/core/serialization/amqp/MapSerializer.kt +++ b/core/src/main/kotlin/net/corda/core/serialization/amqp/MapSerializer.kt @@ -1,6 +1,5 @@ package net.corda.core.serialization.amqp -import net.corda.core.checkNotUnorderedHashMap import org.apache.qpid.proton.codec.Data import java.io.NotSerializableException import java.lang.reflect.ParameterizedType @@ -47,9 +46,9 @@ class MapSerializer(val declaredType: ParameterizedType, factory: SerializerFact // Write map data.putMap() data.enter() - for (entry in obj as Map<*, *>) { - output.writeObjectOrNull(entry.key, data, declaredType.actualTypeArguments[0]) - output.writeObjectOrNull(entry.value, data, declaredType.actualTypeArguments[1]) + for ((key, value) in obj as Map<*, *>) { + output.writeObjectOrNull(key, data, declaredType.actualTypeArguments[0]) + output.writeObjectOrNull(value, data, declaredType.actualTypeArguments[1]) } data.exit() // exit map } @@ -64,4 +63,10 @@ class MapSerializer(val declaredType: ParameterizedType, factory: SerializerFact private fun readEntry(schema: Schema, input: DeserializationInput, entry: Map.Entry) = input.readObjectOrNull(entry.key, schema, declaredType.actualTypeArguments[0]) to input.readObjectOrNull(entry.value, schema, declaredType.actualTypeArguments[1]) +} + +internal fun Class<*>.checkNotUnorderedHashMap() { + if (HashMap::class.java.isAssignableFrom(this) && !LinkedHashMap::class.java.isAssignableFrom(this)) { + throw IllegalArgumentException("Map type $this is unstable under iteration. Suggested fix: use java.util.LinkedHashMap instead.") + } } \ No newline at end of file diff --git a/core/src/main/kotlin/net/corda/core/serialization/amqp/SerializerFactory.kt b/core/src/main/kotlin/net/corda/core/serialization/amqp/SerializerFactory.kt index 7f2d95fddc..0d990aee49 100644 --- a/core/src/main/kotlin/net/corda/core/serialization/amqp/SerializerFactory.kt +++ b/core/src/main/kotlin/net/corda/core/serialization/amqp/SerializerFactory.kt @@ -2,7 +2,6 @@ package net.corda.core.serialization.amqp import com.google.common.primitives.Primitives import com.google.common.reflect.TypeResolver -import net.corda.core.checkNotUnorderedHashMap import net.corda.core.serialization.AllWhitelist import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.CordaSerializable diff --git a/core/src/main/kotlin/net/corda/core/transactions/BaseTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/BaseTransaction.kt index 9f6bb582a5..1bc956c161 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/BaseTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/BaseTransaction.kt @@ -2,7 +2,7 @@ package net.corda.core.transactions import net.corda.core.contracts.* import net.corda.core.identity.Party -import net.corda.core.indexOfOrThrow +import net.corda.core.internal.indexOfOrThrow import net.corda.core.internal.castIfPossible import java.security.PublicKey import java.util.* diff --git a/core/src/main/kotlin/net/corda/core/utilities/KotlinUtils.kt b/core/src/main/kotlin/net/corda/core/utilities/KotlinUtils.kt index 3d55db4c9c..a762aa738c 100644 --- a/core/src/main/kotlin/net/corda/core/utilities/KotlinUtils.kt +++ b/core/src/main/kotlin/net/corda/core/utilities/KotlinUtils.kt @@ -8,10 +8,17 @@ import kotlin.reflect.KProperty // // READ ME FIRST: -// This is a collection of public utilities useful only for Kotlin code. If you're looking to add a public utility that -// is also relevant to Java then put it in Utils.kt. +// This is a collection of public utilities useful only for Kotlin code. Think carefully before adding anything here and +// make sure it's tested and documented. If you're looking to add a public utility that is also relevant to Java then +// don't put it here but in a seperate file called Utils.kt // +/** Like the + operator but throws [ArithmeticException] in case of integer overflow. */ +infix fun Int.exactAdd(b: Int): Int = Math.addExact(this, b) + +/** Like the + operator but throws [ArithmeticException] in case of integer overflow. */ +infix fun Long.exactAdd(b: Long): Long = Math.addExact(this, b) + /** * Get the [Logger] for a class using the syntax * diff --git a/core/src/test/kotlin/net/corda/core/CollectionExtensionTests.kt b/core/src/test/kotlin/net/corda/core/CollectionExtensionTests.kt deleted file mode 100644 index 1fab9fceaa..0000000000 --- a/core/src/test/kotlin/net/corda/core/CollectionExtensionTests.kt +++ /dev/null @@ -1,40 +0,0 @@ -package net.corda.core - -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith - -class CollectionExtensionTests { - @Test - fun `noneOrSingle returns a single item`() { - val collection = listOf(1) - assertEquals(collection.noneOrSingle(), 1) - assertEquals(collection.noneOrSingle { it == 1 }, 1) - } - - @Test - fun `noneOrSingle returns null if item not found`() { - val collection = emptyList() - assertEquals(collection.noneOrSingle(), null) - } - - @Test - fun `noneOrSingle throws if more than one item found`() { - val collection = listOf(1, 2) - assertFailsWith { collection.noneOrSingle() } - assertFailsWith { collection.noneOrSingle { it > 0 } } - } - - @Test - fun `indexOfOrThrow returns index of the given item`() { - val collection = listOf(1, 2) - assertEquals(collection.indexOfOrThrow(1), 0) - assertEquals(collection.indexOfOrThrow(2), 1) - } - - @Test - fun `indexOfOrThrow throws if the given item is not found`() { - val collection = listOf(1) - assertFailsWith { collection.indexOfOrThrow(2) } - } -} diff --git a/core/src/test/kotlin/net/corda/core/StreamsTest.kt b/core/src/test/kotlin/net/corda/core/StreamsTest.kt deleted file mode 100644 index f9b5ebc1ec..0000000000 --- a/core/src/test/kotlin/net/corda/core/StreamsTest.kt +++ /dev/null @@ -1,42 +0,0 @@ -package net.corda.core - -import org.junit.Assert.assertArrayEquals -import org.junit.Test -import java.util.stream.IntStream -import java.util.stream.Stream -import kotlin.test.assertEquals - -class StreamsTest { - @Test - fun `IntProgression stream works`() { - assertArrayEquals(intArrayOf(1, 2, 3, 4), (1..4).stream().toArray()) - assertArrayEquals(intArrayOf(1, 2, 3, 4), (1 until 5).stream().toArray()) - assertArrayEquals(intArrayOf(1, 3), (1..4 step 2).stream().toArray()) - assertArrayEquals(intArrayOf(1, 3), (1..3 step 2).stream().toArray()) - assertArrayEquals(intArrayOf(), (1..0).stream().toArray()) - assertArrayEquals(intArrayOf(1, 0), (1 downTo 0).stream().toArray()) - assertArrayEquals(intArrayOf(3, 1), (3 downTo 0 step 2).stream().toArray()) - assertArrayEquals(intArrayOf(3, 1), (3 downTo 1 step 2).stream().toArray()) - } - - @Test - fun `IntProgression spliterator characteristics and comparator`() { - val rangeCharacteristics = IntStream.range(0, 2).spliterator().characteristics() - val forward = (0..9 step 3).stream().spliterator() - assertEquals(rangeCharacteristics, forward.characteristics()) - assertEquals(null, forward.comparator) - val reverse = (9 downTo 0 step 3).stream().spliterator() - assertEquals(rangeCharacteristics, reverse.characteristics()) - assertEquals(Comparator.reverseOrder(), reverse.comparator) - } - - @Test - fun `Stream toTypedArray works`() { - val a: Array = Stream.of("one", "two").toTypedArray() - assertEquals(Array::class.java, a.javaClass) - assertArrayEquals(arrayOf("one", "two"), a) - val b: Array = Stream.of("one", "two", null).toTypedArray() - assertEquals(Array::class.java, b.javaClass) - assertArrayEquals(arrayOf("one", "two", null), b) - } -} diff --git a/core/src/test/kotlin/net/corda/core/crypto/X509NameConstraintsTest.kt b/core/src/test/kotlin/net/corda/core/crypto/X509NameConstraintsTest.kt index 974f449473..ef6f879409 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/X509NameConstraintsTest.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/X509NameConstraintsTest.kt @@ -1,6 +1,6 @@ package net.corda.core.crypto -import net.corda.core.toTypedArray +import net.corda.core.internal.toTypedArray import net.corda.node.utilities.KEYSTORE_TYPE import net.corda.node.utilities.addOrReplaceCertificate import net.corda.node.utilities.addOrReplaceKey diff --git a/core/src/test/kotlin/net/corda/core/crypto/X509UtilitiesTest.kt b/core/src/test/kotlin/net/corda/core/crypto/X509UtilitiesTest.kt index 1b6e651035..d1da2f6a27 100644 --- a/core/src/test/kotlin/net/corda/core/crypto/X509UtilitiesTest.kt +++ b/core/src/test/kotlin/net/corda/core/crypto/X509UtilitiesTest.kt @@ -5,7 +5,7 @@ import net.corda.core.crypto.Crypto.generateKeyPair import net.corda.core.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME import net.corda.core.crypto.X509Utilities.createSelfSignedCACertificate import net.corda.core.internal.div -import net.corda.core.toTypedArray +import net.corda.core.internal.toTypedArray import net.corda.node.services.config.createKeystoreForCordaNode import net.corda.node.utilities.* import net.corda.testing.MEGA_CORP diff --git a/core/src/test/kotlin/net/corda/core/internal/InternalUtilsTest.kt b/core/src/test/kotlin/net/corda/core/internal/InternalUtilsTest.kt new file mode 100644 index 0000000000..b2f31384db --- /dev/null +++ b/core/src/test/kotlin/net/corda/core/internal/InternalUtilsTest.kt @@ -0,0 +1,90 @@ +package net.corda.core.internal + +import org.assertj.core.api.Assertions +import org.junit.Assert.assertArrayEquals +import org.junit.Test +import java.util.stream.IntStream +import java.util.stream.Stream +import kotlin.test.assertEquals +import kotlin.test.assertFailsWith + +class InternalUtilsTest { + @Test + fun `noneOrSingle on an empty collection`() { + val collection = emptyList() + Assertions.assertThat(collection.noneOrSingle()).isNull() + Assertions.assertThat(collection.noneOrSingle { it == 1 }).isNull() + } + + @Test + fun `noneOrSingle on a singleton collection`() { + val collection = listOf(1) + Assertions.assertThat(collection.noneOrSingle()).isEqualTo(1) + Assertions.assertThat(collection.noneOrSingle { it == 1 }).isEqualTo(1) + Assertions.assertThat(collection.noneOrSingle { it == 2 }).isNull() + } + + @Test + fun `noneOrSingle on a collection with two items`() { + val collection = listOf(1, 2) + assertFailsWith { collection.noneOrSingle() } + Assertions.assertThat(collection.noneOrSingle { it == 1 }).isEqualTo(1) + Assertions.assertThat(collection.noneOrSingle { it == 2 }).isEqualTo(2) + Assertions.assertThat(collection.noneOrSingle { it == 3 }).isNull() + assertFailsWith { collection.noneOrSingle { it > 0 } } + } + + @Test + fun `noneOrSingle on a collection with items 1, 2, 1`() { + val collection = listOf(1, 2, 1) + assertFailsWith { collection.noneOrSingle() } + assertFailsWith { collection.noneOrSingle { it == 1 } } + Assertions.assertThat(collection.noneOrSingle { it == 2 }).isEqualTo(2) + } + + @Test + fun `indexOfOrThrow returns index of the given item`() { + val collection = listOf(1, 2) + assertEquals(collection.indexOfOrThrow(1), 0) + assertEquals(collection.indexOfOrThrow(2), 1) + } + + @Test + fun `indexOfOrThrow throws if the given item is not found`() { + val collection = listOf(1) + assertFailsWith { collection.indexOfOrThrow(2) } + } + + @Test + fun `IntProgression stream works`() { + assertArrayEquals(intArrayOf(1, 2, 3, 4), (1..4).stream().toArray()) + assertArrayEquals(intArrayOf(1, 2, 3, 4), (1 until 5).stream().toArray()) + assertArrayEquals(intArrayOf(1, 3), (1..4 step 2).stream().toArray()) + assertArrayEquals(intArrayOf(1, 3), (1..3 step 2).stream().toArray()) + assertArrayEquals(intArrayOf(), (1..0).stream().toArray()) + assertArrayEquals(intArrayOf(1, 0), (1 downTo 0).stream().toArray()) + assertArrayEquals(intArrayOf(3, 1), (3 downTo 0 step 2).stream().toArray()) + assertArrayEquals(intArrayOf(3, 1), (3 downTo 1 step 2).stream().toArray()) + } + + @Test + fun `IntProgression spliterator characteristics and comparator`() { + val rangeCharacteristics = IntStream.range(0, 2).spliterator().characteristics() + val forward = (0..9 step 3).stream().spliterator() + assertEquals(rangeCharacteristics, forward.characteristics()) + assertEquals(null, forward.comparator) + val reverse = (9 downTo 0 step 3).stream().spliterator() + assertEquals(rangeCharacteristics, reverse.characteristics()) + assertEquals(Comparator.reverseOrder(), reverse.comparator) + } + + @Test + fun `Stream toTypedArray works`() { + val a: Array = Stream.of("one", "two").toTypedArray() + assertEquals(Array::class.java, a.javaClass) + assertArrayEquals(arrayOf("one", "two"), a) + val b: Array = Stream.of("one", "two", null).toTypedArray() + assertEquals(Array::class.java, b.javaClass) + assertArrayEquals(arrayOf("one", "two", null), b) + } +} diff --git a/core/src/test/kotlin/net/corda/core/serialization/amqp/SerializationOutputTests.kt b/core/src/test/kotlin/net/corda/core/serialization/amqp/SerializationOutputTests.kt index 13dc2b22fb..702bfd46f6 100644 --- a/core/src/test/kotlin/net/corda/core/serialization/amqp/SerializationOutputTests.kt +++ b/core/src/test/kotlin/net/corda/core/serialization/amqp/SerializationOutputTests.kt @@ -240,7 +240,7 @@ class SerializationOutputTests { serdes(obj) } - @Test(expected = NotSerializableException::class) + @Test(expected = IllegalArgumentException::class) fun `test dislike of HashMap`() { val obj = WrapHashMap(HashMap()) serdes(obj) diff --git a/docs/source/api-index.rst b/docs/source/api-index.rst index 8498f42e9b..6ecc7de87e 100644 --- a/docs/source/api-index.rst +++ b/docs/source/api-index.rst @@ -11,4 +11,13 @@ This section describes the APIs that are available for the development of CorDap * :doc:`api-flows` * :doc:`api-core-types` -Before reading this page, you should be familiar with the :doc:`key concepts of Corda `. \ No newline at end of file +Before reading this page, you should be familiar with the :doc:`key concepts of Corda `. + +Internal +-------- + +Code that falls into the following package namespaces are for internal use only and not public. In a future release the +node will not load any CorDapp which uses them. + +* Any package in the ``net.corda`` namespace which contains ``.internal`` +* ``net.corda.node`` diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 84eb64d112..006b2a4e40 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -47,6 +47,9 @@ UNRELEASED * Added various query methods to ``LedgerTransaction`` to simplify querying of states and commands. In the same vain ``Command`` is now parameterised on the ``CommandData`` field. +* Kotlin utilities that we deemed useful enough to keep public have been moved out of ``net.corda.core.Utils`` and into + ``net.corda.core.utilities.KotlinUtils``. The other utilities have been marked as internal. + Milestone 13 ------------ diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/RPCStructures.kt b/node-api/src/main/kotlin/net/corda/nodeapi/RPCStructures.kt index 796d0e38f3..9cff1175db 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/RPCStructures.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/RPCStructures.kt @@ -5,11 +5,10 @@ package net.corda.nodeapi import com.esotericsoftware.kryo.Registration import com.esotericsoftware.kryo.Serializer import com.google.common.util.concurrent.ListenableFuture -import net.corda.core.requireExternal +import net.corda.core.CordaRuntimeException import net.corda.core.serialization.* import net.corda.core.toFuture import net.corda.core.toObservable -import net.corda.core.CordaRuntimeException import net.corda.nodeapi.config.OldConfig import rx.Observable import java.io.InputStream @@ -73,4 +72,8 @@ class RPCKryo(observableSerializer: Serializer>, whitelist: Clas type.requireExternal("RPC not allowed to deserialise internal classes") return super.getRegistration(type) } + + private fun Class<*>.requireExternal(msg: String) { + require(!name.startsWith("net.corda.node.") && !name.contains(".internal.")) { "$msg: $name" } + } } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/config/ConfigUtilities.kt b/node-api/src/main/kotlin/net/corda/nodeapi/config/ConfigUtilities.kt index 81455d6e6a..e398b76c4b 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/config/ConfigUtilities.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/config/ConfigUtilities.kt @@ -2,7 +2,7 @@ package net.corda.nodeapi.config import com.typesafe.config.Config import com.typesafe.config.ConfigUtil -import net.corda.core.noneOrSingle +import net.corda.core.internal.noneOrSingle import net.corda.core.utilities.validateX500Name import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.parseNetworkHostAndPort diff --git a/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt index efb4bf8b80..80c4215064 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/DistributedServiceTests.kt @@ -1,6 +1,6 @@ package net.corda.node.services -import net.corda.core.bufferUntilSubscribed +import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.contracts.Amount import net.corda.core.contracts.POUNDS import net.corda.core.identity.Party diff --git a/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt b/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt index a5c059a498..5419891a00 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/statemachine/LargeTransactionsTest.kt @@ -1,7 +1,7 @@ package net.corda.node.services.statemachine import co.paralleluniverse.fibers.Suspendable -import net.corda.core.InputStreamAndHash +import net.corda.core.internal.InputStreamAndHash import net.corda.core.crypto.SecureHash import net.corda.core.flows.* import net.corda.core.identity.Party diff --git a/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt b/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt index 7a11417de3..25b4eeecbf 100644 --- a/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt +++ b/node/src/integration-test/kotlin/net/corda/services/messaging/P2PMessagingTest.kt @@ -3,8 +3,8 @@ package net.corda.services.messaging import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.ListenableFuture import net.corda.core.crypto.random63BitValue -import net.corda.core.elapsedTime import net.corda.core.getOrThrow +import net.corda.core.internal.elapsedTime import net.corda.core.internal.times import net.corda.core.messaging.MessageRecipients import net.corda.core.messaging.SingleMessageRecipient diff --git a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt index e42b76c68c..096829e8b6 100644 --- a/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt +++ b/node/src/main/kotlin/net/corda/node/internal/NodeStartup.kt @@ -6,11 +6,9 @@ import joptsimple.OptionException import net.corda.core.* import net.corda.core.crypto.commonName import net.corda.core.crypto.orgName -import net.corda.core.internal.createDirectories -import net.corda.core.internal.div +import net.corda.core.internal.* import net.corda.node.VersionInfo import net.corda.core.node.services.ServiceInfo -import net.corda.core.internal.Emoji import net.corda.core.utilities.loggerFor import net.corda.node.ArgsParser import net.corda.node.CmdLineOptions diff --git a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt index a598dded88..87f66d24bf 100644 --- a/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt +++ b/node/src/main/kotlin/net/corda/node/services/messaging/ArtemisMessagingServer.kt @@ -9,6 +9,7 @@ import net.corda.core.crypto.X509Utilities.CORDA_CLIENT_TLS import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA import net.corda.core.internal.ThreadBox import net.corda.core.internal.div +import net.corda.core.internal.noneOrSingle import net.corda.core.node.NodeInfo import net.corda.core.node.services.NetworkMapCache import net.corda.core.node.services.NetworkMapCache.MapChange diff --git a/node/src/main/kotlin/net/corda/node/services/network/InMemoryNetworkMapCache.kt b/node/src/main/kotlin/net/corda/node/services/network/InMemoryNetworkMapCache.kt index 25087c0832..bccd62df0c 100644 --- a/node/src/main/kotlin/net/corda/node/services/network/InMemoryNetworkMapCache.kt +++ b/node/src/main/kotlin/net/corda/node/services/network/InMemoryNetworkMapCache.kt @@ -3,7 +3,7 @@ package net.corda.node.services.network import com.google.common.annotations.VisibleForTesting import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.SettableFuture -import net.corda.core.bufferUntilSubscribed +import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.map diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt index 9b455f9544..1e9b9da71e 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionMappingStorage.kt @@ -1,7 +1,7 @@ package net.corda.node.services.persistence import net.corda.core.internal.ThreadBox -import net.corda.core.bufferUntilSubscribed +import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.crypto.SecureHash import net.corda.core.flows.StateMachineRunId import net.corda.core.messaging.DataFeed diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt index 219865b00e..dd63f08291 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt @@ -1,7 +1,7 @@ package net.corda.node.services.persistence import com.google.common.annotations.VisibleForTesting -import net.corda.core.bufferUntilSubscribed +import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.crypto.SecureHash import net.corda.core.messaging.DataFeed import net.corda.core.serialization.SingletonSerializeAsToken diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/InMemoryStateMachineRecordedTransactionMappingStorage.kt b/node/src/main/kotlin/net/corda/node/services/persistence/InMemoryStateMachineRecordedTransactionMappingStorage.kt index 8c4a684a11..740373d3d7 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/InMemoryStateMachineRecordedTransactionMappingStorage.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/InMemoryStateMachineRecordedTransactionMappingStorage.kt @@ -1,7 +1,7 @@ package net.corda.node.services.persistence import net.corda.core.internal.ThreadBox -import net.corda.core.bufferUntilSubscribed +import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.crypto.SecureHash import net.corda.core.flows.StateMachineRunId import net.corda.core.messaging.DataFeed diff --git a/node/src/main/kotlin/net/corda/node/services/statemachine/FlowStateMachineImpl.kt b/node/src/main/kotlin/net/corda/node/services/statemachine/FlowStateMachineImpl.kt index 75d9d4e867..e95059d808 100644 --- a/node/src/main/kotlin/net/corda/node/services/statemachine/FlowStateMachineImpl.kt +++ b/node/src/main/kotlin/net/corda/node/services/statemachine/FlowStateMachineImpl.kt @@ -6,12 +6,12 @@ import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.strands.Strand import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.SettableFuture -import net.corda.core.abbreviate import net.corda.core.crypto.SecureHash import net.corda.core.crypto.random63BitValue import net.corda.core.flows.* import net.corda.core.identity.Party import net.corda.core.internal.FlowStateMachine +import net.corda.core.internal.abbreviate import net.corda.core.internal.staticField import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.* @@ -122,7 +122,7 @@ class FlowStateMachineImpl(override val id: StateMachineRunId, actionOnEnd(Try.Success(result), false) _resultFuture?.set(result) logic.progressTracker?.currentStep = ProgressTracker.DONE - logger.debug { "Flow finished with result $result" } + logger.debug { "Flow finished with result ${result.toString().abbreviate(300)}" } } private fun createTransaction() { diff --git a/node/src/main/kotlin/net/corda/node/services/statemachine/StateMachineManager.kt b/node/src/main/kotlin/net/corda/node/services/statemachine/StateMachineManager.kt index 009c5a10ec..b3752c4112 100644 --- a/node/src/main/kotlin/net/corda/node/services/statemachine/StateMachineManager.kt +++ b/node/src/main/kotlin/net/corda/node/services/statemachine/StateMachineManager.kt @@ -9,7 +9,7 @@ import com.google.common.collect.HashMultimap import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.MoreExecutors import net.corda.core.internal.ThreadBox -import net.corda.core.bufferUntilSubscribed +import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.crypto.SecureHash import net.corda.core.crypto.random63BitValue import net.corda.core.flows.FlowException diff --git a/node/src/main/kotlin/net/corda/node/services/transactions/BFTSMaRt.kt b/node/src/main/kotlin/net/corda/node/services/transactions/BFTSMaRt.kt index a7119c3e73..53f5cccd52 100644 --- a/node/src/main/kotlin/net/corda/node/services/transactions/BFTSMaRt.kt +++ b/node/src/main/kotlin/net/corda/node/services/transactions/BFTSMaRt.kt @@ -27,7 +27,7 @@ import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.deserialize import net.corda.core.serialization.serialize -import net.corda.core.toTypedArray +import net.corda.core.internal.toTypedArray import net.corda.core.transactions.FilteredTransaction import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.debug diff --git a/node/src/main/kotlin/net/corda/node/services/vault/HibernateVaultQueryImpl.kt b/node/src/main/kotlin/net/corda/node/services/vault/HibernateVaultQueryImpl.kt index c7cb8b6647..f891989cd1 100644 --- a/node/src/main/kotlin/net/corda/node/services/vault/HibernateVaultQueryImpl.kt +++ b/node/src/main/kotlin/net/corda/node/services/vault/HibernateVaultQueryImpl.kt @@ -1,7 +1,7 @@ package net.corda.node.services.vault import net.corda.core.internal.ThreadBox -import net.corda.core.bufferUntilSubscribed +import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.contracts.ContractState import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.StateRef diff --git a/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt b/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt index 3a7dc5ad0e..12edbc340f 100644 --- a/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt +++ b/node/src/main/kotlin/net/corda/node/services/vault/NodeVaultService.kt @@ -13,7 +13,7 @@ import io.requery.query.RowExpression import net.corda.contracts.asset.Cash import net.corda.contracts.asset.OnLedgerAsset import net.corda.core.internal.ThreadBox -import net.corda.core.bufferUntilSubscribed +import net.corda.core.internal.bufferUntilSubscribed import net.corda.core.contracts.* import net.corda.core.crypto.SecureHash import net.corda.core.crypto.containsAny @@ -30,7 +30,7 @@ import net.corda.core.serialization.SerializationDefaults.STORAGE_CONTEXT import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.deserialize import net.corda.core.serialization.serialize -import net.corda.core.tee +import net.corda.core.internal.tee import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.WireTransaction import net.corda.core.utilities.* diff --git a/node/src/main/kotlin/net/corda/node/shell/InteractiveShell.kt b/node/src/main/kotlin/net/corda/node/shell/InteractiveShell.kt index 945a5318f9..0c48fa471a 100644 --- a/node/src/main/kotlin/net/corda/node/shell/InteractiveShell.kt +++ b/node/src/main/kotlin/net/corda/node/shell/InteractiveShell.kt @@ -12,10 +12,7 @@ import com.google.common.util.concurrent.SettableFuture import net.corda.core.* import net.corda.core.flows.FlowInitiator import net.corda.core.flows.FlowLogic -import net.corda.core.internal.FlowStateMachine -import net.corda.core.internal.createDirectories -import net.corda.core.internal.div -import net.corda.core.internal.write +import net.corda.core.internal.* import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.StateMachineUpdate import net.corda.core.internal.Emoji diff --git a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt index d574684c01..47dea9e954 100644 --- a/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/messaging/TwoPartyTradeFlowTests.kt @@ -19,6 +19,7 @@ import net.corda.core.identity.AnonymousParty import net.corda.core.identity.AnonymousPartyAndPath import net.corda.core.identity.Party import net.corda.core.internal.FlowStateMachine +import net.corda.core.internal.rootCause import net.corda.core.map import net.corda.core.messaging.DataFeed import net.corda.core.messaging.SingleMessageRecipient @@ -26,8 +27,6 @@ import net.corda.core.messaging.StateMachineTransactionMapping import net.corda.core.node.NodeInfo import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.Vault -import net.corda.core.rootCause -import net.corda.core.serialization.serialize import net.corda.core.toFuture import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder diff --git a/node/src/test/kotlin/net/corda/node/utilities/ObservablesTests.kt b/node/src/test/kotlin/net/corda/node/utilities/ObservablesTests.kt index 41c45e1a46..b74b902b09 100644 --- a/node/src/test/kotlin/net/corda/node/utilities/ObservablesTests.kt +++ b/node/src/test/kotlin/net/corda/node/utilities/ObservablesTests.kt @@ -1,8 +1,8 @@ package net.corda.node.utilities import com.google.common.util.concurrent.SettableFuture -import net.corda.core.bufferUntilSubscribed -import net.corda.core.tee +import net.corda.core.internal.bufferUntilSubscribed +import net.corda.core.internal.tee import net.corda.testing.node.makeTestDataSourceProperties import org.assertj.core.api.Assertions.assertThat import org.junit.After diff --git a/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkisRegistrationHelperTest.kt b/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkisRegistrationHelperTest.kt index 95580f6d82..1eeae40142 100644 --- a/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkisRegistrationHelperTest.kt +++ b/node/src/test/kotlin/net/corda/node/utilities/registration/NetworkisRegistrationHelperTest.kt @@ -5,7 +5,7 @@ import com.nhaarman.mockito_kotlin.eq import com.nhaarman.mockito_kotlin.mock import net.corda.core.crypto.* import net.corda.core.internal.exists -import net.corda.core.toTypedArray +import net.corda.core.internal.toTypedArray import net.corda.node.utilities.loadKeyStore import net.corda.testing.ALICE import net.corda.testing.getTestX509Name diff --git a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt index 7fab70f1e1..aea97e7834 100644 --- a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt +++ b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt @@ -3,7 +3,6 @@ package net.corda.attachmentdemo import co.paralleluniverse.fibers.Suspendable import joptsimple.OptionParser import net.corda.client.rpc.CordaRPCClient -import net.corda.core.InputStreamAndHash import net.corda.core.contracts.Contract import net.corda.core.contracts.ContractState import net.corda.core.contracts.TransactionType @@ -15,6 +14,7 @@ import net.corda.core.getOrThrow import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.internal.Emoji +import net.corda.core.internal.InputStreamAndHash import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.startTrackedFlow import net.corda.core.transactions.LedgerTransaction diff --git a/samples/irs-demo/src/test/kotlin/net/corda/irs/api/NodeInterestRatesTest.kt b/samples/irs-demo/src/test/kotlin/net/corda/irs/api/NodeInterestRatesTest.kt index 79d5d36e30..4374b695bf 100644 --- a/samples/irs-demo/src/test/kotlin/net/corda/irs/api/NodeInterestRatesTest.kt +++ b/samples/irs-demo/src/test/kotlin/net/corda/irs/api/NodeInterestRatesTest.kt @@ -6,7 +6,6 @@ import net.corda.contracts.asset.CASH import net.corda.contracts.asset.Cash import net.corda.contracts.asset.`issued by` import net.corda.contracts.asset.`owned by` -import net.corda.core.bd import net.corda.core.contracts.* import net.corda.core.crypto.MerkleTreeException import net.corda.core.crypto.generateKeyPair @@ -81,7 +80,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() { val q = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M") val res = oracle.query(listOf(q)) assertEquals(1, res.size) - assertEquals("0.678".bd, res[0].value) + assertEquals(BigDecimal("0.678"), res[0].value) assertEquals(q, res[0].of) } } @@ -163,7 +162,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() { database.transaction { val tx = makeTX() val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M") - val badFix = Fix(fixOf, "0.6789".bd) + val badFix = Fix(fixOf, BigDecimal("0.6789")) tx.addCommand(badFix, oracle.identity.owningKey) val wtx = tx.toWireTransaction() val ftx = wtx.buildFilteredTransaction(Predicate { x -> fixCmdFilter(x) }) @@ -212,7 +211,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() { val tx = TransactionType.General.Builder(null) val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M") val oracle = n2.info.serviceIdentities(NodeInterestRates.Oracle.type).first() - val flow = FilteredRatesFlow(tx, oracle, fixOf, "0.675".bd, "0.1".bd) + val flow = FilteredRatesFlow(tx, oracle, fixOf, BigDecimal("0.675"), BigDecimal("0.1")) LogHelper.setLevel("rates") mockNet.runNetwork() val future = n1.services.startFlow(flow).resultFuture @@ -221,7 +220,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() { // We should now have a valid fix of our tx from the oracle. val fix = tx.toWireTransaction().commands.map { it.value as Fix }.first() assertEquals(fixOf, fix.of) - assertEquals("0.678".bd, fix.value) + assertEquals(BigDecimal("0.678"), fix.value) mockNet.stopNodes() } diff --git a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/BFTNotaryCordform.kt b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/BFTNotaryCordform.kt index e9d72c01e6..b57011a62d 100644 --- a/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/BFTNotaryCordform.kt +++ b/samples/notary-demo/src/main/kotlin/net/corda/notarydemo/BFTNotaryCordform.kt @@ -11,8 +11,8 @@ import net.corda.node.utilities.ServiceIdentityGenerator import net.corda.cordform.CordformDefinition import net.corda.cordform.CordformContext import net.corda.cordform.CordformNode -import net.corda.core.stream -import net.corda.core.toTypedArray +import net.corda.core.internal.stream +import net.corda.core.internal.toTypedArray import net.corda.core.utilities.NetworkHostAndPort import net.corda.node.services.transactions.minCorrectReplicas import org.bouncycastle.asn1.x500.X500Name diff --git a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/portfolio/Portfolio.kt b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/portfolio/Portfolio.kt index b91186362e..4c603102d4 100644 --- a/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/portfolio/Portfolio.kt +++ b/samples/simm-valuation-demo/src/main/kotlin/net/corda/vega/portfolio/Portfolio.kt @@ -3,11 +3,12 @@ package net.corda.vega.portfolio import net.corda.client.rpc.notUsed import net.corda.core.contracts.* import net.corda.core.identity.Party +import net.corda.core.internal.sum import net.corda.core.messaging.CordaRPCOps import net.corda.core.node.ServiceHub -import net.corda.core.sum import net.corda.vega.contracts.IRSState import net.corda.vega.contracts.SwapData +import java.math.BigDecimal import java.time.LocalDate /** @@ -22,7 +23,7 @@ data class Portfolio(private val tradeStateAndRefs: List>, val swaps: List by lazy { trades.map { it.swap } } val refs: List by lazy { tradeStateAndRefs.map { it.ref } } - fun getNotionalForParty(party: Party) = trades.map { it.swap.getLegForParty(party).notional }.sum() + fun getNotionalForParty(party: Party): BigDecimal = trades.map { it.swap.getLegForParty(party).notional }.sum() fun update(curTrades: List>): Portfolio { return copy(tradeStateAndRefs = curTrades) diff --git a/test-utils/src/main/kotlin/net/corda/testing/node/TestClock.kt b/test-utils/src/main/kotlin/net/corda/testing/node/TestClock.kt index 32728b2380..d0303085d8 100644 --- a/test-utils/src/main/kotlin/net/corda/testing/node/TestClock.kt +++ b/test-utils/src/main/kotlin/net/corda/testing/node/TestClock.kt @@ -4,6 +4,7 @@ import net.corda.core.internal.until import net.corda.core.serialization.SerializeAsToken import net.corda.core.serialization.SerializeAsTokenContext import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken +import net.corda.core.internal.until import net.corda.node.utilities.MutableClock import java.time.Clock import java.time.Duration diff --git a/webserver/src/main/kotlin/net/corda/webserver/WebServer.kt b/webserver/src/main/kotlin/net/corda/webserver/WebServer.kt index 99420e2abb..25388e96c1 100644 --- a/webserver/src/main/kotlin/net/corda/webserver/WebServer.kt +++ b/webserver/src/main/kotlin/net/corda/webserver/WebServer.kt @@ -4,7 +4,7 @@ package net.corda.webserver import com.typesafe.config.ConfigException import net.corda.core.internal.div -import net.corda.core.rootCause +import net.corda.core.internal.rootCause import net.corda.webserver.internal.NodeWebServer import org.slf4j.LoggerFactory import java.lang.management.ManagementFactory