mirror of
https://github.com/corda/corda.git
synced 2025-01-14 16:59:52 +00:00
Merge pull request #764 from corda/colljos-merge-230418
OS -> ENT merge
This commit is contained in:
commit
5ae35b70dc
@ -3228,7 +3228,7 @@ public static final class net.corda.core.transactions.FilteredTransaction$Compan
|
|||||||
@org.jetbrains.annotations.NotNull public final List inputsOfType(Class)
|
@org.jetbrains.annotations.NotNull public final List inputsOfType(Class)
|
||||||
public String toString()
|
public String toString()
|
||||||
public final void verify()
|
public final void verify()
|
||||||
public static final net.corda.core.transactions.LedgerTransaction$Companion Companion
|
@java.lang.Deprecated public static final net.corda.core.transactions.LedgerTransaction$Companion Companion
|
||||||
##
|
##
|
||||||
public static final class net.corda.core.transactions.LedgerTransaction$InOutGroup extends java.lang.Object
|
public static final class net.corda.core.transactions.LedgerTransaction$InOutGroup extends java.lang.Object
|
||||||
public <init>(List, List, Object)
|
public <init>(List, List, Object)
|
||||||
@ -3334,7 +3334,7 @@ public static final class net.corda.core.transactions.NotaryChangeWireTransactio
|
|||||||
@org.jetbrains.annotations.NotNull public final net.corda.core.transactions.SignedTransaction withAdditionalSignature(java.security.KeyPair, net.corda.core.crypto.SignatureMetadata)
|
@org.jetbrains.annotations.NotNull public final net.corda.core.transactions.SignedTransaction withAdditionalSignature(java.security.KeyPair, net.corda.core.crypto.SignatureMetadata)
|
||||||
@org.jetbrains.annotations.NotNull public final net.corda.core.transactions.SignedTransaction withAdditionalSignature(net.corda.core.crypto.TransactionSignature)
|
@org.jetbrains.annotations.NotNull public final net.corda.core.transactions.SignedTransaction withAdditionalSignature(net.corda.core.crypto.TransactionSignature)
|
||||||
@org.jetbrains.annotations.NotNull public final net.corda.core.transactions.SignedTransaction withAdditionalSignatures(Iterable)
|
@org.jetbrains.annotations.NotNull public final net.corda.core.transactions.SignedTransaction withAdditionalSignatures(Iterable)
|
||||||
public static final net.corda.core.transactions.SignedTransaction$Companion Companion
|
@java.lang.Deprecated public static final net.corda.core.transactions.SignedTransaction$Companion Companion
|
||||||
##
|
##
|
||||||
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.transactions.SignedTransaction$SignaturesMissingException extends java.security.SignatureException implements net.corda.core.CordaThrowable, net.corda.core.contracts.NamedByHash
|
@net.corda.core.serialization.CordaSerializable public static final class net.corda.core.transactions.SignedTransaction$SignaturesMissingException extends java.security.SignatureException implements net.corda.core.CordaThrowable, net.corda.core.contracts.NamedByHash
|
||||||
public <init>(Set, List, net.corda.core.crypto.SecureHash)
|
public <init>(Set, List, net.corda.core.crypto.SecureHash)
|
||||||
|
@ -183,8 +183,8 @@ allprojects {
|
|||||||
|
|
||||||
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
languageVersion = "1.1"
|
languageVersion = "1.2"
|
||||||
apiVersion = "1.1"
|
apiVersion = "1.2"
|
||||||
jvmTarget = "1.8"
|
jvmTarget = "1.8"
|
||||||
javaParameters = true // Useful for reflection.
|
javaParameters = true // Useful for reflection.
|
||||||
}
|
}
|
||||||
|
@ -474,3 +474,8 @@ fun NotarisationRequest.generateSignature(serviceHub: ServiceHub): NotarisationR
|
|||||||
}
|
}
|
||||||
|
|
||||||
val PublicKey.hash: SecureHash get() = encoded.sha256()
|
val PublicKey.hash: SecureHash get() = encoded.sha256()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension method for providing a sumBy method that processes and returns a Long
|
||||||
|
*/
|
||||||
|
fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long = this.map { selector(it) }.sum()
|
||||||
|
@ -140,7 +140,3 @@ fun <V> Future<V>.getOrThrow(timeout: Duration? = null): V = try {
|
|||||||
throw e.cause!!
|
throw e.cause!!
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Extension method for providing a sumBy method that processes and returns a Long
|
|
||||||
*/
|
|
||||||
fun <T> Iterable<T>.sumByLong(selector: (T) -> Long): Long = this.map { selector(it) }.sum()
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
package net.corda.core.flows;
|
package net.corda.core.flows;
|
||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable;
|
import co.paralleluniverse.fibers.Suspendable;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.primitives.Primitives;
|
import com.google.common.primitives.Primitives;
|
||||||
import net.corda.core.identity.Party;
|
import net.corda.core.identity.Party;
|
||||||
import net.corda.testing.core.TestConstants;
|
import net.corda.testing.core.TestConstants;
|
||||||
@ -23,13 +24,12 @@ import org.junit.Test;
|
|||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import static java.util.Collections.emptyList;
|
|
||||||
import static net.corda.testing.core.TestUtils.singleIdentity;
|
import static net.corda.testing.core.TestUtils.singleIdentity;
|
||||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
public class FlowsInJavaTest {
|
public class FlowsInJavaTest {
|
||||||
private final MockNetwork mockNet = new MockNetwork(emptyList());
|
private final MockNetwork mockNet = new MockNetwork(ImmutableList.of("net.corda.core.flows"));
|
||||||
private StartedMockNode aliceNode;
|
private StartedMockNode aliceNode;
|
||||||
private StartedMockNode bobNode;
|
private StartedMockNode bobNode;
|
||||||
private Party bob;
|
private Party bob;
|
||||||
@ -48,7 +48,6 @@ public class FlowsInJavaTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void suspendableActionInsideUnwrap() throws Exception {
|
public void suspendableActionInsideUnwrap() throws Exception {
|
||||||
bobNode.registerInitiatedFlow(SendHelloAndThenReceive.class);
|
|
||||||
Future<String> result = aliceNode.startFlow(new SendInUnwrapFlow(bob));
|
Future<String> result = aliceNode.startFlow(new SendInUnwrapFlow(bob));
|
||||||
mockNet.runNetwork();
|
mockNet.runNetwork();
|
||||||
assertThat(result.get()).isEqualTo("Hello");
|
assertThat(result.get()).isEqualTo("Hello");
|
||||||
|
@ -51,7 +51,7 @@ class CollectSignaturesFlowTests {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
|
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts", "net.corda.core.flows"))
|
||||||
aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
aliceNode = mockNet.createPartyNode(ALICE_NAME)
|
||||||
bobNode = mockNet.createPartyNode(BOB_NAME)
|
bobNode = mockNet.createPartyNode(BOB_NAME)
|
||||||
charlieNode = mockNet.createPartyNode(CHARLIE_NAME)
|
charlieNode = mockNet.createPartyNode(CHARLIE_NAME)
|
||||||
@ -66,12 +66,6 @@ class CollectSignaturesFlowTests {
|
|||||||
mockNet.stopNodes()
|
mockNet.stopNodes()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerFlowOnAllNodes(flowClass: KClass<out FlowLogic<*>>) {
|
|
||||||
listOf(aliceNode, bobNode, charlieNode).forEach {
|
|
||||||
it.registerInitiatedFlow(flowClass.java)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// With this flow, the initiator starts the "CollectTransactionFlow". It is then the responders responsibility to
|
// With this flow, the initiator starts the "CollectTransactionFlow". It is then the responders responsibility to
|
||||||
// override "checkTransaction" and add whatever logic their require to verify the SignedTransaction they are
|
// override "checkTransaction" and add whatever logic their require to verify the SignedTransaction they are
|
||||||
// receiving off the wire.
|
// receiving off the wire.
|
||||||
@ -120,7 +114,6 @@ class CollectSignaturesFlowTests {
|
|||||||
// Normally this is handled by TransactionKeyFlow, but here we have to manually let A know about the identity
|
// Normally this is handled by TransactionKeyFlow, but here we have to manually let A know about the identity
|
||||||
aliceNode.services.identityService.verifyAndRegisterIdentity(bConfidentialIdentity)
|
aliceNode.services.identityService.verifyAndRegisterIdentity(bConfidentialIdentity)
|
||||||
}
|
}
|
||||||
registerFlowOnAllNodes(TestFlow.Responder::class)
|
|
||||||
val magicNumber = 1337
|
val magicNumber = 1337
|
||||||
val parties = listOf(alice, bConfidentialIdentity.party, charlie)
|
val parties = listOf(alice, bConfidentialIdentity.party, charlie)
|
||||||
val state = DummyContract.MultiOwnerState(magicNumber, parties)
|
val state = DummyContract.MultiOwnerState(magicNumber, parties)
|
||||||
|
@ -48,12 +48,10 @@ class ResolveTransactionsFlowTest {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts"))
|
mockNet = InternalMockNetwork(cordappPackages = listOf("net.corda.testing.contracts", "net.corda.core.internal"))
|
||||||
notaryNode = mockNet.defaultNotaryNode
|
notaryNode = mockNet.defaultNotaryNode
|
||||||
megaCorpNode = mockNet.createPartyNode(CordaX500Name("MegaCorp", "London", "GB"))
|
megaCorpNode = mockNet.createPartyNode(CordaX500Name("MegaCorp", "London", "GB"))
|
||||||
miniCorpNode = mockNet.createPartyNode(CordaX500Name("MiniCorp", "London", "GB"))
|
miniCorpNode = mockNet.createPartyNode(CordaX500Name("MiniCorp", "London", "GB"))
|
||||||
megaCorpNode.registerInitiatedFlow(TestResponseFlow::class.java)
|
|
||||||
miniCorpNode.registerInitiatedFlow(TestResponseFlow::class.java)
|
|
||||||
notary = mockNet.defaultNotaryIdentity
|
notary = mockNet.defaultNotaryIdentity
|
||||||
megaCorp = megaCorpNode.info.singleIdentity()
|
megaCorp = megaCorpNode.info.singleIdentity()
|
||||||
miniCorp = miniCorpNode.info.singleIdentity()
|
miniCorp = miniCorpNode.info.singleIdentity()
|
||||||
|
@ -165,24 +165,6 @@ Nodes are created on the ``MockNetwork`` using:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Registering a node's initiated flows
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Regular Corda nodes automatically register any response flows defined in their installed CorDapps. When using a
|
|
||||||
``MockNetwork``, each ``StartedMockNode`` must manually register any responder flows it wishes to use.
|
|
||||||
|
|
||||||
Responder flows are registered as follows:
|
|
||||||
|
|
||||||
.. container:: codeset
|
|
||||||
|
|
||||||
.. sourcecode:: kotlin
|
|
||||||
|
|
||||||
nodeA.registerInitiatedFlow(ExampleFlow.Acceptor::class.java)
|
|
||||||
|
|
||||||
.. sourcecode:: java
|
|
||||||
|
|
||||||
nodeA.registerInitiatedFlow(ExampleFlow.Acceptor.class);
|
|
||||||
|
|
||||||
Running the network
|
Running the network
|
||||||
^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
package net.corda.docs.tutorial.mocknetwork
|
package net.corda.docs.tutorial.mocknetwork
|
||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
import net.corda.core.contracts.requireThat
|
import net.corda.core.contracts.requireThat
|
||||||
import net.corda.core.flows.FlowLogic
|
import net.corda.core.flows.FlowLogic
|
||||||
import net.corda.core.flows.FlowSession
|
import net.corda.core.flows.FlowSession
|
||||||
@ -72,10 +73,9 @@ class TutorialMockNetwork {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
mockNet = MockNetwork(emptyList())
|
mockNet = MockNetwork(ImmutableList.of("net.corda.docs.tutorial.mocknetwork"))
|
||||||
nodeA = mockNet.createPartyNode()
|
nodeA = mockNet.createPartyNode()
|
||||||
nodeB = mockNet.createPartyNode()
|
nodeB = mockNet.createPartyNode()
|
||||||
nodeB.registerInitiatedFlow(FlowB::class.java)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
|
@ -61,10 +61,6 @@ transactions are valid) inside a ``database.transaction``. All node flows run w
|
|||||||
nodes themselves, but any time we need to use the database directly from a unit test, you need to provide a database
|
nodes themselves, but any time we need to use the database directly from a unit test, you need to provide a database
|
||||||
transaction as shown here.
|
transaction as shown here.
|
||||||
|
|
||||||
With regards to initiated flows (see :doc:`flow-state-machines` for information on initiated and initiating flows), the
|
|
||||||
full node automatically registers them by scanning the CorDapp jars. In a unit test environment this is not possible so
|
|
||||||
``MockNode`` has the ``registerInitiatedFlow`` method to manually register an initiated flow.
|
|
||||||
|
|
||||||
.. MockNetwork message manipulation
|
.. MockNetwork message manipulation
|
||||||
.. --------------------------------
|
.. --------------------------------
|
||||||
.. The MockNetwork has the ability to manipulate message streams. You can use this to test your flows behaviour on corrupted,
|
.. The MockNetwork has the ability to manipulate message streams. You can use this to test your flows behaviour on corrupted,
|
||||||
|
@ -15,6 +15,7 @@ import net.corda.behave.file.currentDirectory
|
|||||||
import net.corda.behave.logging.getLogger
|
import net.corda.behave.logging.getLogger
|
||||||
import net.corda.behave.process.output.OutputListener
|
import net.corda.behave.process.output.OutputListener
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import rx.Subscriber
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -153,8 +154,9 @@ open class Command(
|
|||||||
return exitCode
|
return exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun use(action: (Command, Observable<String>) -> Unit = { _, _ -> }): Int {
|
fun use(subscriber: Subscriber<String>, action: (Command, Observable<String>) -> Unit = { _, _ -> }): Int {
|
||||||
try {
|
try {
|
||||||
|
output.subscribe(subscriber)
|
||||||
start()
|
start()
|
||||||
action(this, output)
|
action(this, output)
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
package net.corda.behave.scenarios
|
|
||||||
|
|
||||||
import cucumber.api.java.After
|
|
||||||
import cucumber.api.java.Before
|
|
||||||
|
|
||||||
@Suppress("KDocMissingDocumentation")
|
|
||||||
class ScenarioHooks(private val state: ScenarioState) {
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun beforeScenario() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
fun afterScenario() {
|
|
||||||
state.stopNetwork()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -4,7 +4,7 @@ import net.corda.behave.scenarios.ScenarioState
|
|||||||
import net.corda.behave.scenarios.api.StepsBlock
|
import net.corda.behave.scenarios.api.StepsBlock
|
||||||
import net.corda.behave.scenarios.helpers.Vault
|
import net.corda.behave.scenarios.helpers.Vault
|
||||||
import net.corda.core.contracts.ContractState
|
import net.corda.core.contracts.ContractState
|
||||||
import net.corda.core.utilities.sumByLong
|
import net.corda.core.internal.sumByLong
|
||||||
import net.corda.finance.contracts.asset.Cash
|
import net.corda.finance.contracts.asset.Cash
|
||||||
|
|
||||||
class VaultSteps : StepsBlock {
|
class VaultSteps : StepsBlock {
|
||||||
|
@ -31,8 +31,7 @@ class CommandTests {
|
|||||||
@Test
|
@Test
|
||||||
fun `output stream for command can be observed`() {
|
fun `output stream for command can be observed`() {
|
||||||
val subscriber = TestSubscriber<String>()
|
val subscriber = TestSubscriber<String>()
|
||||||
val exitCode = Command(listOf("ls", "/")).use { _, output ->
|
val exitCode = Command(listOf("ls", "/")).use(subscriber) { _, output ->
|
||||||
output.subscribe(subscriber)
|
|
||||||
subscriber.awaitTerminalEvent()
|
subscriber.awaitTerminalEvent()
|
||||||
subscriber.assertCompleted()
|
subscriber.assertCompleted()
|
||||||
subscriber.assertNoErrors()
|
subscriber.assertNoErrors()
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* R3 Proprietary and Confidential
|
|
||||||
*
|
|
||||||
* Copyright (c) 2018 R3 Limited. All rights reserved.
|
|
||||||
*
|
|
||||||
* The intellectual and technical concepts contained herein are proprietary to R3 and its suppliers and are protected by trade secret law.
|
|
||||||
*
|
|
||||||
* Distribution of this file or any portion thereof via any medium without the express permission of R3 is strictly prohibited.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.corda.behave.service
|
|
||||||
|
|
||||||
import net.corda.behave.service.database.PostgreSQLService
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.junit.Ignore
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
class PostreSQLServiceTests {
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun `postgres can be started and stopped`() {
|
|
||||||
val service = PostgreSQLService("test-postgres", 12345, "postgres")
|
|
||||||
val didStart = service.start()
|
|
||||||
service.stop()
|
|
||||||
assertThat(didStart).isTrue()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -13,40 +13,53 @@ package net.corda.nodeapi.internal
|
|||||||
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
|
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner
|
||||||
import net.corda.core.contracts.Contract
|
import net.corda.core.contracts.Contract
|
||||||
import net.corda.core.contracts.ContractClassName
|
import net.corda.core.contracts.ContractClassName
|
||||||
|
import net.corda.core.contracts.UpgradedContract
|
||||||
|
import net.corda.core.contracts.UpgradedContractWithLegacyConstraint
|
||||||
import net.corda.core.internal.copyTo
|
import net.corda.core.internal.copyTo
|
||||||
import net.corda.core.internal.deleteIfExists
|
import net.corda.core.internal.deleteIfExists
|
||||||
|
import net.corda.core.internal.logElapsedTime
|
||||||
import net.corda.core.internal.read
|
import net.corda.core.internal.read
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
|
||||||
import java.nio.file.StandardCopyOption
|
import java.nio.file.StandardCopyOption
|
||||||
|
import java.util.Collections.singleton
|
||||||
|
|
||||||
|
// When scanning of the CorDapp Jar is performed without "corda-core.jar" being the in the classpath, there is no way to appreciate
|
||||||
|
// relationships between those interfaces, therefore they have to be listed explicitly.
|
||||||
|
val coreContractClasses = setOf(Contract::class, UpgradedContractWithLegacyConstraint::class, UpgradedContract::class)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans the jar for contracts.
|
* Scans the jar for contracts.
|
||||||
* @returns: found contract class names or null if none found
|
* @returns: found contract class names or null if none found
|
||||||
*/
|
*/
|
||||||
fun scanJarForContracts(cordappJar: Path): List<ContractClassName> {
|
fun scanJarForContracts(cordappJar: Path): List<ContractClassName> {
|
||||||
val currentClassLoader = Contract::class.java.classLoader
|
|
||||||
val scanResult = FastClasspathScanner()
|
val scanResult = FastClasspathScanner()
|
||||||
.addClassLoader(currentClassLoader)
|
// A set of a single element may look odd, but if this is removed "Path" which itself is an `Iterable`
|
||||||
.overrideClasspath(cordappJar, Paths.get(Contract::class.java.protectionDomain.codeSource.location.toURI()))
|
// is getting broken into pieces to scan individually, which doesn't yield desired effect.
|
||||||
|
.overrideClasspath(singleton(cordappJar))
|
||||||
.scan()
|
.scan()
|
||||||
val contracts = (scanResult.getNamesOfClassesImplementing(Contract::class.qualifiedName) ).distinct()
|
val contracts = coreContractClasses.flatMap { contractClass -> scanResult.getNamesOfClassesImplementing(contractClass.qualifiedName) }.distinct()
|
||||||
|
|
||||||
// Only keep instantiable contracts
|
// Only keep instantiable contracts
|
||||||
return URLClassLoader(arrayOf(cordappJar.toUri().toURL()), currentClassLoader).use {
|
return URLClassLoader(arrayOf(cordappJar.toUri().toURL()), Contract::class.java.classLoader).use {
|
||||||
contracts.map(it::loadClass).filter { !it.isInterface && !Modifier.isAbstract(it.modifiers) }
|
contracts.map(it::loadClass).filter { !it.isInterface && !Modifier.isAbstract(it.modifiers) }
|
||||||
}.map { it.name }
|
}.map { it.name }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val logger = LoggerFactory.getLogger("ClassloaderUtils")
|
||||||
|
|
||||||
fun <T> withContractsInJar(jarInputStream: InputStream, withContracts: (List<ContractClassName>, InputStream) -> T): T {
|
fun <T> withContractsInJar(jarInputStream: InputStream, withContracts: (List<ContractClassName>, InputStream) -> T): T {
|
||||||
val tempFile = Files.createTempFile("attachment", ".jar")
|
val tempFile = Files.createTempFile("attachment", ".jar")
|
||||||
try {
|
try {
|
||||||
jarInputStream.copyTo(tempFile, StandardCopyOption.REPLACE_EXISTING)
|
jarInputStream.copyTo(tempFile, StandardCopyOption.REPLACE_EXISTING)
|
||||||
val contracts = scanJarForContracts(tempFile.toAbsolutePath())
|
val cordappJar = tempFile.toAbsolutePath()
|
||||||
|
val contracts = logElapsedTime("Contracts loading for '$cordappJar'", logger) {
|
||||||
|
scanJarForContracts(cordappJar)
|
||||||
|
}
|
||||||
return tempFile.read { withContracts(contracts, it) }
|
return tempFile.read { withContracts(contracts, it) }
|
||||||
} finally {
|
} finally {
|
||||||
tempFile.deleteIfExists()
|
tempFile.deleteIfExists()
|
||||||
|
@ -27,6 +27,7 @@ import net.corda.core.serialization.SerializeAsToken
|
|||||||
import net.corda.core.utilities.contextLogger
|
import net.corda.core.utilities.contextLogger
|
||||||
import net.corda.node.internal.classloading.requireAnnotation
|
import net.corda.node.internal.classloading.requireAnnotation
|
||||||
import net.corda.node.services.config.NodeConfiguration
|
import net.corda.node.services.config.NodeConfiguration
|
||||||
|
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.File
|
||||||
@ -251,13 +252,7 @@ class CordappLoader private constructor(private val cordappJarPaths: List<Restri
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun findContractClassNames(scanResult: RestrictedScanResult): List<String> {
|
private fun findContractClassNames(scanResult: RestrictedScanResult): List<String> {
|
||||||
return (scanResult.getNamesOfClassesImplementing(Contract::class) +
|
return coreContractClasses.flatMap { scanResult.getNamesOfClassesImplementing(it) }.distinct()
|
||||||
scanResult.getNamesOfClassesImplementing(UpgradedContract::class) +
|
|
||||||
// Even though UpgradedContractWithLegacyConstraint implements UpgradedContract
|
|
||||||
// we need to specify it separately. Otherwise, classes implementing UpgradedContractWithLegacyConstraint
|
|
||||||
// don't get picked up.
|
|
||||||
scanResult.getNamesOfClassesImplementing(UpgradedContractWithLegacyConstraint::class))
|
|
||||||
.distinct()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findPlugins(cordappJarPath: RestrictedURL): List<SerializationWhitelist> {
|
private fun findPlugins(cordappJarPath: RestrictedURL): List<SerializationWhitelist> {
|
||||||
|
@ -59,7 +59,6 @@ class TraderDemoTest : IntegrationTest() {
|
|||||||
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser)),
|
startNode(providedName = DUMMY_BANK_B_NAME, rpcUsers = listOf(demoUser)),
|
||||||
startNode(providedName = BOC_NAME, rpcUsers = listOf(bankUser))
|
startNode(providedName = BOC_NAME, rpcUsers = listOf(bankUser))
|
||||||
).map { (it.getOrThrow() as InProcess) }
|
).map { (it.getOrThrow() as InProcess) }
|
||||||
nodeA.registerInitiatedFlow(BuyerFlow::class.java)
|
|
||||||
val (nodeARpc, nodeBRpc) = listOf(nodeA, nodeB).map {
|
val (nodeARpc, nodeBRpc) = listOf(nodeA, nodeB).map {
|
||||||
val client = CordaRPCClient(it.rpcAddress)
|
val client = CordaRPCClient(it.rpcAddress)
|
||||||
client.start(demoUser.username, demoUser.password).proxy
|
client.start(demoUser.username, demoUser.password).proxy
|
||||||
|
Loading…
Reference in New Issue
Block a user