From 12fd451919a82964370693dfe8e45a3dc6627339 Mon Sep 17 00:00:00 2001 From: Adel El-Beik <48713346+adelel1@users.noreply.github.com> Date: Thu, 17 Feb 2022 14:07:11 +0000 Subject: [PATCH 01/37] ENT-6588 Restrict database operations platform flag (#7053) (#7073) * ENT-6588 Restrict database operations platform flag Put the restricting of database operations in `RestrictedConnection` and `RestrictedEntityManager` behind a platform version flag. `RESTRICTED_DATABASE_OPERATIONS = 7` was added to signify this. If the version is less than 7, then the database operations will not be restricted. A warning is logged to indicate that they are using potentially dangerous methods. If the version is 7 or greater, then the database operations are restricted and throw an error if called. Co-authored-by: Dan Newton --- .../core/internal/PlatformVersionSwitches.kt | 1 + .../RestrictedConnectionFlowTest.kt | 52 ++- .../RestrictedEntityManagerFlowTest.kt | 58 +++- .../persistence/RestrictedConnection.kt | 41 +-- .../RestrictedDatabaseOperations.kt | 31 ++ .../persistence/RestrictedEntityManager.kt | 32 +- .../persistence/RestrictedConnectionTest.kt | 311 +++++++++++++++--- .../RestrictedEntityManagerTest.kt | 153 ++++++++- .../net/corda/node/internal/AbstractNode.kt | 4 +- 9 files changed, 559 insertions(+), 124 deletions(-) create mode 100644 node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedDatabaseOperations.kt diff --git a/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt b/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt index 8d24cb03d3..95fdbb72d7 100644 --- a/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt +++ b/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt @@ -6,4 +6,5 @@ The text constant describes the feature and the numeric specifies the platform v */ object PlatformVersionSwitches { const val ENABLE_P2P_COMPRESSION = 7 + const val RESTRICTED_DATABASE_OPERATIONS = 7 } \ No newline at end of file diff --git a/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedConnectionFlowTest.kt b/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedConnectionFlowTest.kt index f948c75f37..e00e65ec44 100644 --- a/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedConnectionFlowTest.kt +++ b/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedConnectionFlowTest.kt @@ -4,14 +4,15 @@ import co.paralleluniverse.fibers.Suspendable import net.corda.core.flows.FlowLogic import net.corda.core.flows.InitiatingFlow import net.corda.core.identity.CordaX500Name +import net.corda.core.internal.PLATFORM_VERSION import net.corda.core.utilities.getOrThrow import net.corda.nodeapi.internal.persistence.RestrictedConnection import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetworkParameters import net.corda.testing.node.StartedMockNode +import net.corda.testing.node.internal.enclosedCordapp import org.assertj.core.api.Assertions import org.junit.After -import org.junit.Before import org.junit.Test import kotlin.test.assertTrue @@ -38,40 +39,63 @@ class RestrictedConnectionFlowTest { } @InitiatingFlow - class TestCloseMethodIsBlocked : FlowLogic() { + class TestClearWarningsMethodIsBlocked : FlowLogic() { @Suspendable override fun call() { val connection = serviceHub.jdbcSession() - connection.close() + connection.clearWarnings() } } - @Before - fun init() { - mockNetwork = MockNetwork(MockNetworkParameters()) - aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) - } - @After fun done() { mockNetwork.stopNodes() } @Test(timeout=300_000) - fun testIfItIsRestrictedConnection() { + fun `restricted connection is returned from ServiceHub#jdbcSession`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) assertTrue { aliceNode.startFlow(TestIfItIsRestrictedConnection()).get() } mockNetwork.runNetwork() } @Test(timeout=300_000) - fun testMethodsAreBlocked() { + fun `restricted methods are blocked when the target platform is the current corda version`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) .isThrownBy { aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() } - .withMessageContaining("This method cannot be called via ServiceHub.jdbcSession.") + .withMessageContaining("ServiceHub.jdbcSession.setAutoCommit is restricted and cannot be called") Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) - .isThrownBy { aliceNode.startFlow(TestCloseMethodIsBlocked()).getOrThrow() } - .withMessageContaining("This method cannot be called via ServiceHub.jdbcSession.") + .isThrownBy { aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.jdbcSession.clearWarnings is restricted and cannot be called") + + mockNetwork.runNetwork() + } + + @Test(timeout=300_000) + fun `restricted methods are blocked when the target platform is 7`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 7)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) + Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) + .isThrownBy { aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.jdbcSession.setAutoCommit is restricted and cannot be called") + + Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) + .isThrownBy { aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.jdbcSession.clearWarnings is restricted and cannot be called") + + mockNetwork.runNetwork() + } + + @Test(timeout=300_000) + fun `restricted methods are not blocked when the target platform is 6`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 6)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) + aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() + aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow() mockNetwork.runNetwork() } diff --git a/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedEntityManagerFlowTest.kt b/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedEntityManagerFlowTest.kt index 7da2ff26ff..995440973d 100644 --- a/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedEntityManagerFlowTest.kt +++ b/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedEntityManagerFlowTest.kt @@ -4,14 +4,15 @@ import co.paralleluniverse.fibers.Suspendable import net.corda.core.flows.FlowLogic import net.corda.core.flows.InitiatingFlow import net.corda.core.identity.CordaX500Name +import net.corda.core.internal.PLATFORM_VERSION import net.corda.core.utilities.getOrThrow import net.corda.nodeapi.internal.persistence.RestrictedEntityManager import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetworkParameters import net.corda.testing.node.StartedMockNode +import net.corda.testing.node.internal.enclosedCordapp import org.assertj.core.api.Assertions import org.junit.After -import org.junit.Before import org.junit.Test import kotlin.test.assertTrue @@ -25,7 +26,7 @@ class RestrictedEntityManagerFlowTest { @Suspendable override fun call() : Boolean { var result = false - serviceHub.withEntityManager() { + serviceHub.withEntityManager { result = this is RestrictedEntityManager } return result @@ -33,11 +34,11 @@ class RestrictedEntityManagerFlowTest { } @InitiatingFlow - class TestCloseMethodIsBlocked : FlowLogic() { + class TestGetMetamodelMethodIsBlocked : FlowLogic() { @Suspendable override fun call() { - serviceHub.withEntityManager() { - this.close() + serviceHub.withEntityManager { + this.metamodel } } } @@ -46,38 +47,61 @@ class RestrictedEntityManagerFlowTest { class TestJoinTransactionMethodIsBlocked : FlowLogic() { @Suspendable override fun call() { - serviceHub.withEntityManager() { + serviceHub.withEntityManager { this.joinTransaction() } } } - @Before - fun init() { - mockNetwork = MockNetwork(MockNetworkParameters()) - aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) - } - @After fun done() { mockNetwork.stopNodes() } @Test(timeout=300_000) - fun testIfItIsRestrictedConnection() { + fun `restricted connection is returned from ServiceHub#withEntityManager`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) assertTrue { aliceNode.startFlow(TestIfItIsRestrictedEntityManager()).get() } mockNetwork.runNetwork() } @Test(timeout=300_000) - fun testMethodsAreBlocked() { + fun `restricted methods are blocked when the target platform is the current corda version`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) - .isThrownBy { aliceNode.startFlow(TestCloseMethodIsBlocked()).getOrThrow() } - .withMessageContaining("This method cannot be called via ServiceHub.withEntityManager.") + .isThrownBy { aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.withEntityManager.getMetamodel is restricted and cannot be called") Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) .isThrownBy { aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() } - .withMessageContaining("This method cannot be called via ServiceHub.withEntityManager.") + .withMessageContaining("ServiceHub.withEntityManager.joinTransaction is restricted and cannot be called") + + mockNetwork.runNetwork() + } + + @Test(timeout=300_000) + fun `restricted methods are blocked when the target platform is 7`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 7)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) + Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) + .isThrownBy { aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.withEntityManager.getMetamodel is restricted and cannot be called") + + Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) + .isThrownBy { aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.withEntityManager.joinTransaction is restricted and cannot be called") + + mockNetwork.runNetwork() + } + + @Test(timeout=300_000) + fun `restricted methods are not blocked when the target platform is 6`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 6)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) + aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow() + aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() mockNetwork.runNetwork() } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnection.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnection.kt index 997cdc3ebd..a2a471c364 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnection.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnection.kt @@ -1,5 +1,6 @@ package net.corda.nodeapi.internal.persistence +import net.corda.core.node.ServiceHub import java.sql.Connection import java.sql.Savepoint import java.util.concurrent.Executor @@ -8,73 +9,73 @@ import java.util.concurrent.Executor * A delegate of [Connection] which disallows some operations. */ @Suppress("TooManyFunctions") -class RestrictedConnection(private val delegate : Connection) : Connection by delegate { +class RestrictedConnection(private val delegate: Connection, private val serviceHub: ServiceHub) : Connection by delegate { override fun abort(executor: Executor?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("abort", serviceHub) { delegate.abort(executor) } } override fun clearWarnings() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("clearWarnings", serviceHub) { delegate.clearWarnings() } } override fun close() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("close", serviceHub) { delegate.close() } } override fun commit() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("commit", serviceHub) { delegate.commit() } } override fun setSavepoint(): Savepoint? { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + return restrictDatabaseOperationFromJdbcSession("setSavepoint", serviceHub) { delegate.setSavepoint() } } - override fun setSavepoint(name : String?): Savepoint? { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + override fun setSavepoint(name: String?): Savepoint? { + return restrictDatabaseOperationFromJdbcSession("setSavepoint", serviceHub) { delegate.setSavepoint(name) } } override fun releaseSavepoint(savepoint: Savepoint?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("releaseSavepoint", serviceHub) { delegate.releaseSavepoint(savepoint) } } override fun rollback() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("rollback", serviceHub) { delegate.rollback() } } override fun rollback(savepoint: Savepoint?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("rollback", serviceHub) { delegate.rollback(savepoint) } } - override fun setCatalog(catalog : String?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + override fun setCatalog(catalog: String?) { + restrictDatabaseOperationFromJdbcSession("setCatalog", serviceHub) { delegate.catalog = catalog } } override fun setTransactionIsolation(level: Int) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setTransactionIsolation", serviceHub) { delegate.transactionIsolation = level } } override fun setTypeMap(map: MutableMap>?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setTypeMap", serviceHub) { delegate.typeMap = map } } override fun setHoldability(holdability: Int) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setHoldability", serviceHub) { delegate.holdability = holdability } } override fun setSchema(schema: String?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setSchema", serviceHub) { delegate.schema = schema } } override fun setNetworkTimeout(executor: Executor?, milliseconds: Int) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setNetworkTimeout", serviceHub) { delegate.setNetworkTimeout(executor, milliseconds) } } override fun setAutoCommit(autoCommit: Boolean) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setAutoCommit", serviceHub) { delegate.autoCommit = autoCommit } } override fun setReadOnly(readOnly: Boolean) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setReadOnly", serviceHub) { delegate.isReadOnly = readOnly } } } \ No newline at end of file diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedDatabaseOperations.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedDatabaseOperations.kt new file mode 100644 index 0000000000..bc5cbc055f --- /dev/null +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedDatabaseOperations.kt @@ -0,0 +1,31 @@ +package net.corda.nodeapi.internal.persistence + +import net.corda.core.internal.PlatformVersionSwitches.RESTRICTED_DATABASE_OPERATIONS +import net.corda.core.internal.warnOnce +import net.corda.core.node.ServiceHub +import org.slf4j.LoggerFactory + +private val log = LoggerFactory.getLogger("RestrictedDatabaseOperations") + +internal inline fun restrictDatabaseOperationFromJdbcSession(method: String, serviceHub: ServiceHub, operation: () -> T): T { + return restrictDatabaseOperation("ServiceHub.jdbcSession.$method", serviceHub, operation) +} + +internal inline fun restrictDatabaseOperationFromEntityManager(method: String, serviceHub: ServiceHub, operation: () -> T): T { + return restrictDatabaseOperation("ServiceHub.withEntityManager.$method", serviceHub, operation) +} + +internal inline fun restrictDatabaseOperation(method: String, serviceHub: ServiceHub, operation: () -> T): T { + return if (serviceHub.getAppContext().cordapp.targetPlatformVersion >= RESTRICTED_DATABASE_OPERATIONS) { + throw UnsupportedOperationException("$method is restricted and cannot be called") + } else { + log.warnOnce( + "$method should not be called, as manipulating database transactions and connections breaks the Corda flow state machine in " + + "ways that only become evident in failure scenarios. Purely for API backwards compatibility reasons, the prior " + + "behaviour is continued for target platform versions less than $RESTRICTED_DATABASE_OPERATIONS. You should evolve " + + "the CorDapp away from using these problematic APIs as soon as possible. For target platform version of " + + "$RESTRICTED_DATABASE_OPERATIONS or above, an exception will be thrown instead." + ) + operation() + } +} \ No newline at end of file diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManager.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManager.kt index 1ea4f2c4fd..d6d2672c0d 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManager.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManager.kt @@ -1,5 +1,6 @@ package net.corda.nodeapi.internal.persistence +import net.corda.core.node.ServiceHub import javax.persistence.EntityManager import javax.persistence.EntityTransaction import javax.persistence.LockModeType @@ -8,56 +9,59 @@ import javax.persistence.metamodel.Metamodel /** * A delegate of [EntityManager] which disallows some operations. */ -class RestrictedEntityManager(private val delegate: EntityManager) : EntityManager by delegate { +class RestrictedEntityManager(private val delegate: EntityManager, private val serviceHub: ServiceHub) : EntityManager by delegate { override fun getTransaction(): EntityTransaction { - return RestrictedEntityTransaction(delegate.transaction) + return RestrictedEntityTransaction(delegate.transaction, serviceHub) } override fun close() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("close", serviceHub) { delegate.close() } } override fun unwrap(cls: Class?): T { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + return restrictDatabaseOperationFromEntityManager("unwrap", serviceHub) { delegate.unwrap(cls) } } override fun getDelegate(): Any { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + return restrictDatabaseOperationFromEntityManager("getDelegate", serviceHub) { delegate.delegate } } override fun getMetamodel(): Metamodel? { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + return restrictDatabaseOperationFromEntityManager("getMetamodel", serviceHub) { delegate.metamodel } } override fun joinTransaction() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("joinTransaction", serviceHub) { delegate.joinTransaction() } } override fun lock(entity: Any?, lockMode: LockModeType?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.lock(entity, lockMode) } } override fun lock(entity: Any?, lockMode: LockModeType?, properties: MutableMap?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.lock(entity, lockMode, properties) } } override fun setProperty(propertyName: String?, value: Any?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.setProperty(propertyName, value) } } } -class RestrictedEntityTransaction(private val delegate: EntityTransaction) : EntityTransaction by delegate { +class RestrictedEntityTransaction( + private val delegate: EntityTransaction, + private val serviceHub: ServiceHub +) : EntityTransaction by delegate { override fun rollback() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("EntityTransaction.rollback", serviceHub) { delegate.rollback() } } override fun commit() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("EntityTransaction.commit", serviceHub) { delegate.commit() } } override fun begin() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("EntityTransaction.begin", serviceHub) { delegate.begin() } } } \ No newline at end of file diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnectionTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnectionTest.kt index 3708360bfc..39f2d7af73 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnectionTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnectionTest.kt @@ -1,104 +1,337 @@ package net.corda.nodeapi.internal.persistence import com.nhaarman.mockito_kotlin.mock +import com.nhaarman.mockito_kotlin.whenever +import net.corda.core.cordapp.Cordapp +import net.corda.core.cordapp.CordappContext +import net.corda.core.internal.PLATFORM_VERSION +import net.corda.core.node.ServiceHub import org.junit.Test import java.sql.Connection import java.sql.Savepoint class RestrictedConnectionTest { - private val connection : Connection = mock() - private val savePoint : Savepoint = mock() - private val restrictedConnection : RestrictedConnection = RestrictedConnection(connection) + private val connection: Connection = mock() + private val savePoint: Savepoint = mock() + private val cordapp = mock() + private val cordappContext = CordappContext.create(cordapp, null, javaClass.classLoader, mock()) + private val serviceHub = mock().apply { + whenever(getAppContext()).thenReturn(cordappContext) + } + private val restrictedConnection: RestrictedConnection = RestrictedConnection(connection, serviceHub) companion object { - private const val TEST_STRING : String = "test" - private const val TEST_INT : Int = 1 + private const val TEST_STRING: String = "test" + private const val TEST_INT: Int = 1 } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testAbort() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `abort with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.abort { println("I'm just an executor for this test...") } } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testClearWarnings() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `clearWarnings with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.clearWarnings() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testClose() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `close with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.close() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testCommit() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `commit with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.commit() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetSavepoint() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSavepoint with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.setSavepoint() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetSavepointWithName() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSavepoint with name with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.setSavepoint(TEST_STRING) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testReleaseSavepoint() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `releaseSavepoint with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.releaseSavepoint(savePoint) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testRollback() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `rollback with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.rollback() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testRollbackWithSavepoint() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `rollbackWithSavepoint with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.rollback(savePoint) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetCatalog() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setCatalog with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.catalog = TEST_STRING } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetTransactionIsolation() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setTransactionIsolation with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.transactionIsolation = TEST_INT } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetTypeMap() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setTypeMap with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) val map: MutableMap> = mutableMapOf() restrictedConnection.typeMap = map } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetHoldability() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setHoldability with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.holdability = TEST_INT } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetSchema() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSchema with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.schema = TEST_STRING } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetNetworkTimeout() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setNetworkTimeout with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetAutoCommit() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setAutoCommit with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.autoCommit = true } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetReadOnly() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setReadOnly with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) + restrictedConnection.isReadOnly = true + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `abort with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.abort { println("I'm just an executor for this test...") } + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `clearWarnings with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.clearWarnings() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `close with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.close() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `commit with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.commit() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSavepoint with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.setSavepoint() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSavepoint with name with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.setSavepoint(TEST_STRING) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `releaseSavepoint with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.releaseSavepoint(savePoint) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `rollback with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.rollback() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `rollbackWithSavepoint with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.rollback(savePoint) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setCatalog with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.catalog = TEST_STRING + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setTransactionIsolation with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.transactionIsolation = TEST_INT + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setTypeMap with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + val map: MutableMap> = mutableMapOf() + restrictedConnection.typeMap = map + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setHoldability with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.holdability = TEST_INT + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSchema with target platform version of current 7 unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.schema = TEST_STRING + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setNetworkTimeout with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setAutoCommit with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.autoCommit = true + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setReadOnly with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.isReadOnly = true + } + + @Test(timeout = 300_000) + fun `abort with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.abort { println("I'm just an executor for this test...") } + } + + @Test(timeout = 300_000) + fun `clearWarnings with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.clearWarnings() + } + + @Test(timeout = 300_000) + fun `close with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.close() + } + + @Test(timeout = 300_000) + fun `commit with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.commit() + } + + @Test(timeout = 300_000) + fun `setSavepoint with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.setSavepoint() + } + + @Test(timeout = 300_000) + fun `setSavepoint with name with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.setSavepoint(TEST_STRING) + } + + @Test(timeout = 300_000) + fun `releaseSavepoint with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.releaseSavepoint(savePoint) + } + + @Test(timeout = 300_000) + fun `rollback with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.rollback() + } + + @Test(timeout = 300_000) + fun `rollbackWithSavepoint with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.rollback(savePoint) + } + + @Test(timeout = 300_000) + fun `setCatalog with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.catalog = TEST_STRING + } + + @Test(timeout = 300_000) + fun `setTransactionIsolation with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.transactionIsolation = TEST_INT + } + + @Test(timeout = 300_000) + fun `setTypeMap with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + val map: MutableMap> = mutableMapOf() + restrictedConnection.typeMap = map + } + + @Test(timeout = 300_000) + fun `setHoldability with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.holdability = TEST_INT + } + + @Test(timeout = 300_000) + fun `setSchema with target platform version of current 6 unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.schema = TEST_STRING + } + + @Test(timeout = 300_000) + fun `setNetworkTimeout with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT) + } + + @Test(timeout = 300_000) + fun `setAutoCommit with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.autoCommit = true + } + + @Test(timeout = 300_000) + fun `setReadOnly with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) restrictedConnection.isReadOnly = true } } \ No newline at end of file diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManagerTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManagerTest.kt index 6f53ade01c..92994a7fab 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManagerTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManagerTest.kt @@ -3,6 +3,10 @@ package net.corda.nodeapi.internal.persistence import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.whenever +import net.corda.core.cordapp.Cordapp +import net.corda.core.cordapp.CordappContext +import net.corda.core.internal.PLATFORM_VERSION +import net.corda.core.node.ServiceHub import org.junit.Test import javax.persistence.EntityManager import javax.persistence.EntityTransaction @@ -12,47 +16,160 @@ import kotlin.test.assertTrue class RestrictedEntityManagerTest { private val entitymanager = mock() private val transaction = mock() - private val restrictedEntityManager = RestrictedEntityManager(entitymanager) + private val cordapp = mock() + private val cordappContext = CordappContext.create(cordapp, null, javaClass.classLoader, mock()) + private val serviceHub = mock().apply { + whenever(getAppContext()).thenReturn(cordappContext) + } + private val restrictedEntityManager = RestrictedEntityManager(entitymanager, serviceHub) - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testClose() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `close with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedEntityManager.close() } @Test(timeout = 300_000) - fun testClear() { + fun `clear with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedEntityManager.clear() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testGetMetaModel() { - restrictedEntityManager.getMetamodel() + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `getMetaModel with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) + restrictedEntityManager.metamodel } @Test(timeout = 300_000) - fun testGetTransaction() { + fun `getTransaction with target platform version of current corda version executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) whenever(entitymanager.transaction).doReturn(transaction) assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testJoinTransaction() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `joinTransaction with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedEntityManager.joinTransaction() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testLockWithTwoParameters() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `lock with two parameters with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testLockWithThreeParameters() { - val map: MutableMap = mutableMapOf() - restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC,map) + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `lock with three parameters with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) + val map: MutableMap = mutableMapOf() + restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetProperty() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setProperty with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) + restrictedEntityManager.setProperty("number", 12) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `close with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.close() + } + + @Test(timeout = 300_000) + fun `clear with target platform version of 7 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.clear() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `getMetaModel with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.metamodel + } + + @Test(timeout = 300_000) + fun `getTransaction with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + whenever(entitymanager.transaction).doReturn(transaction) + assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `joinTransaction with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.joinTransaction() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `lock with two parameters with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `lock with three parameters with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + val map: MutableMap = mutableMapOf() + restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setProperty with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.setProperty("number", 12) + } + + @Test(timeout = 300_000) + fun `close with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedEntityManager.close() + } + + @Test(timeout = 300_000) + fun `clear with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedEntityManager.clear() + } + + @Test(timeout = 300_000) + fun `getMetaModel with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedEntityManager.metamodel + } + + @Test(timeout = 300_000) + fun `getTransaction with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + whenever(entitymanager.transaction).doReturn(transaction) + assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction) + } + + @Test(timeout = 300_000) + fun `joinTransaction with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedEntityManager.joinTransaction() + } + + @Test(timeout = 300_000) + fun `lock with two parameters with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC) + } + + @Test(timeout = 300_000) + fun `lock with three parameters with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + val map: MutableMap = mutableMapOf() + restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map) + } + + @Test(timeout = 300_000) + fun `setProperty with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) restrictedEntityManager.setProperty("number", 12) } } \ No newline at end of file diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index 0b1807445a..97355d8c14 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -1196,7 +1196,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, /** * Exposes the database connection as a [RestrictedConnection] to the users. */ - override fun jdbcSession(): Connection = RestrictedConnection(database.createSession()) + override fun jdbcSession(): Connection = RestrictedConnection(database.createSession(), services) @Suppress("TooGenericExceptionCaught") override fun withEntityManager(block: EntityManager.() -> T): T { @@ -1206,7 +1206,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, withSavePoint { savepoint -> // Restrict what entity manager they can use inside the block try { - block(RestrictedEntityManager(manager)).also { + block(RestrictedEntityManager(manager, services)).also { if (!manager.transaction.rollbackOnly) { manager.flush() } else { From 470bce8a6b401faaaf0bd7eb0989e76c7048c1e4 Mon Sep 17 00:00:00 2001 From: Adel El-Beik <48713346+adelel1@users.noreply.github.com> Date: Thu, 17 Feb 2022 16:59:34 +0000 Subject: [PATCH 02/37] ENT-6588 Restrict database operations platform flag (#7053) (#7073) (#7074) * ENT-6588 Restrict database operations platform flag Put the restricting of database operations in `RestrictedConnection` and `RestrictedEntityManager` behind a platform version flag. `RESTRICTED_DATABASE_OPERATIONS = 7` was added to signify this. If the version is less than 7, then the database operations will not be restricted. A warning is logged to indicate that they are using potentially dangerous methods. If the version is 7 or greater, then the database operations are restricted and throw an error if called. Co-authored-by: Dan Newton Co-authored-by: Dan Newton --- .../core/internal/PlatformVersionSwitches.kt | 1 + .../RestrictedConnectionFlowTest.kt | 52 ++- .../RestrictedEntityManagerFlowTest.kt | 58 +++- .../persistence/RestrictedConnection.kt | 41 +-- .../RestrictedDatabaseOperations.kt | 31 ++ .../persistence/RestrictedEntityManager.kt | 32 +- .../persistence/RestrictedConnectionTest.kt | 311 +++++++++++++++--- .../RestrictedEntityManagerTest.kt | 153 ++++++++- .../net/corda/node/internal/AbstractNode.kt | 4 +- 9 files changed, 559 insertions(+), 124 deletions(-) create mode 100644 node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedDatabaseOperations.kt diff --git a/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt b/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt index 9ab3269653..4f9c64b9df 100644 --- a/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt +++ b/core/src/main/kotlin/net/corda/core/internal/PlatformVersionSwitches.kt @@ -16,4 +16,5 @@ object PlatformVersionSwitches { const val LIMIT_KEYS_IN_SIGNATURE_CONSTRAINTS = 5 const val BATCH_DOWNLOAD_COUNTERPARTY_BACKCHAIN = 6 const val ENABLE_P2P_COMPRESSION = 7 + const val RESTRICTED_DATABASE_OPERATIONS = 7 } \ No newline at end of file diff --git a/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedConnectionFlowTest.kt b/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedConnectionFlowTest.kt index f948c75f37..e00e65ec44 100644 --- a/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedConnectionFlowTest.kt +++ b/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedConnectionFlowTest.kt @@ -4,14 +4,15 @@ import co.paralleluniverse.fibers.Suspendable import net.corda.core.flows.FlowLogic import net.corda.core.flows.InitiatingFlow import net.corda.core.identity.CordaX500Name +import net.corda.core.internal.PLATFORM_VERSION import net.corda.core.utilities.getOrThrow import net.corda.nodeapi.internal.persistence.RestrictedConnection import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetworkParameters import net.corda.testing.node.StartedMockNode +import net.corda.testing.node.internal.enclosedCordapp import org.assertj.core.api.Assertions import org.junit.After -import org.junit.Before import org.junit.Test import kotlin.test.assertTrue @@ -38,40 +39,63 @@ class RestrictedConnectionFlowTest { } @InitiatingFlow - class TestCloseMethodIsBlocked : FlowLogic() { + class TestClearWarningsMethodIsBlocked : FlowLogic() { @Suspendable override fun call() { val connection = serviceHub.jdbcSession() - connection.close() + connection.clearWarnings() } } - @Before - fun init() { - mockNetwork = MockNetwork(MockNetworkParameters()) - aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) - } - @After fun done() { mockNetwork.stopNodes() } @Test(timeout=300_000) - fun testIfItIsRestrictedConnection() { + fun `restricted connection is returned from ServiceHub#jdbcSession`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) assertTrue { aliceNode.startFlow(TestIfItIsRestrictedConnection()).get() } mockNetwork.runNetwork() } @Test(timeout=300_000) - fun testMethodsAreBlocked() { + fun `restricted methods are blocked when the target platform is the current corda version`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) .isThrownBy { aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() } - .withMessageContaining("This method cannot be called via ServiceHub.jdbcSession.") + .withMessageContaining("ServiceHub.jdbcSession.setAutoCommit is restricted and cannot be called") Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) - .isThrownBy { aliceNode.startFlow(TestCloseMethodIsBlocked()).getOrThrow() } - .withMessageContaining("This method cannot be called via ServiceHub.jdbcSession.") + .isThrownBy { aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.jdbcSession.clearWarnings is restricted and cannot be called") + + mockNetwork.runNetwork() + } + + @Test(timeout=300_000) + fun `restricted methods are blocked when the target platform is 7`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 7)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) + Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) + .isThrownBy { aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.jdbcSession.setAutoCommit is restricted and cannot be called") + + Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) + .isThrownBy { aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.jdbcSession.clearWarnings is restricted and cannot be called") + + mockNetwork.runNetwork() + } + + @Test(timeout=300_000) + fun `restricted methods are not blocked when the target platform is 6`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 6)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) + aliceNode.startFlow(TestAutoCommitMethodIsBlocked()).getOrThrow() + aliceNode.startFlow(TestClearWarningsMethodIsBlocked()).getOrThrow() mockNetwork.runNetwork() } diff --git a/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedEntityManagerFlowTest.kt b/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedEntityManagerFlowTest.kt index 7da2ff26ff..995440973d 100644 --- a/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedEntityManagerFlowTest.kt +++ b/node-api-tests/src/test/kotlin/net/corda/nodeapitests/internal/persistence/RestrictedEntityManagerFlowTest.kt @@ -4,14 +4,15 @@ import co.paralleluniverse.fibers.Suspendable import net.corda.core.flows.FlowLogic import net.corda.core.flows.InitiatingFlow import net.corda.core.identity.CordaX500Name +import net.corda.core.internal.PLATFORM_VERSION import net.corda.core.utilities.getOrThrow import net.corda.nodeapi.internal.persistence.RestrictedEntityManager import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNetworkParameters import net.corda.testing.node.StartedMockNode +import net.corda.testing.node.internal.enclosedCordapp import org.assertj.core.api.Assertions import org.junit.After -import org.junit.Before import org.junit.Test import kotlin.test.assertTrue @@ -25,7 +26,7 @@ class RestrictedEntityManagerFlowTest { @Suspendable override fun call() : Boolean { var result = false - serviceHub.withEntityManager() { + serviceHub.withEntityManager { result = this is RestrictedEntityManager } return result @@ -33,11 +34,11 @@ class RestrictedEntityManagerFlowTest { } @InitiatingFlow - class TestCloseMethodIsBlocked : FlowLogic() { + class TestGetMetamodelMethodIsBlocked : FlowLogic() { @Suspendable override fun call() { - serviceHub.withEntityManager() { - this.close() + serviceHub.withEntityManager { + this.metamodel } } } @@ -46,38 +47,61 @@ class RestrictedEntityManagerFlowTest { class TestJoinTransactionMethodIsBlocked : FlowLogic() { @Suspendable override fun call() { - serviceHub.withEntityManager() { + serviceHub.withEntityManager { this.joinTransaction() } } } - @Before - fun init() { - mockNetwork = MockNetwork(MockNetworkParameters()) - aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) - } - @After fun done() { mockNetwork.stopNodes() } @Test(timeout=300_000) - fun testIfItIsRestrictedConnection() { + fun `restricted connection is returned from ServiceHub#withEntityManager`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) assertTrue { aliceNode.startFlow(TestIfItIsRestrictedEntityManager()).get() } mockNetwork.runNetwork() } @Test(timeout=300_000) - fun testMethodsAreBlocked() { + fun `restricted methods are blocked when the target platform is the current corda version`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = PLATFORM_VERSION)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) - .isThrownBy { aliceNode.startFlow(TestCloseMethodIsBlocked()).getOrThrow() } - .withMessageContaining("This method cannot be called via ServiceHub.withEntityManager.") + .isThrownBy { aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.withEntityManager.getMetamodel is restricted and cannot be called") Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) .isThrownBy { aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() } - .withMessageContaining("This method cannot be called via ServiceHub.withEntityManager.") + .withMessageContaining("ServiceHub.withEntityManager.joinTransaction is restricted and cannot be called") + + mockNetwork.runNetwork() + } + + @Test(timeout=300_000) + fun `restricted methods are blocked when the target platform is 7`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 7)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) + Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) + .isThrownBy { aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.withEntityManager.getMetamodel is restricted and cannot be called") + + Assertions.assertThatExceptionOfType(UnsupportedOperationException::class.java) + .isThrownBy { aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() } + .withMessageContaining("ServiceHub.withEntityManager.joinTransaction is restricted and cannot be called") + + mockNetwork.runNetwork() + } + + @Test(timeout=300_000) + fun `restricted methods are not blocked when the target platform is 6`() { + mockNetwork = MockNetwork(MockNetworkParameters(listOf(enclosedCordapp().copy(targetPlatformVersion = 6)))) + aliceNode = mockNetwork.createPartyNode(CordaX500Name("Alice", "London", "GB")) + aliceNode.startFlow(TestGetMetamodelMethodIsBlocked()).getOrThrow() + aliceNode.startFlow(TestJoinTransactionMethodIsBlocked()).getOrThrow() mockNetwork.runNetwork() } diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnection.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnection.kt index 997cdc3ebd..a2a471c364 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnection.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnection.kt @@ -1,5 +1,6 @@ package net.corda.nodeapi.internal.persistence +import net.corda.core.node.ServiceHub import java.sql.Connection import java.sql.Savepoint import java.util.concurrent.Executor @@ -8,73 +9,73 @@ import java.util.concurrent.Executor * A delegate of [Connection] which disallows some operations. */ @Suppress("TooManyFunctions") -class RestrictedConnection(private val delegate : Connection) : Connection by delegate { +class RestrictedConnection(private val delegate: Connection, private val serviceHub: ServiceHub) : Connection by delegate { override fun abort(executor: Executor?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("abort", serviceHub) { delegate.abort(executor) } } override fun clearWarnings() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("clearWarnings", serviceHub) { delegate.clearWarnings() } } override fun close() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("close", serviceHub) { delegate.close() } } override fun commit() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("commit", serviceHub) { delegate.commit() } } override fun setSavepoint(): Savepoint? { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + return restrictDatabaseOperationFromJdbcSession("setSavepoint", serviceHub) { delegate.setSavepoint() } } - override fun setSavepoint(name : String?): Savepoint? { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + override fun setSavepoint(name: String?): Savepoint? { + return restrictDatabaseOperationFromJdbcSession("setSavepoint", serviceHub) { delegate.setSavepoint(name) } } override fun releaseSavepoint(savepoint: Savepoint?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("releaseSavepoint", serviceHub) { delegate.releaseSavepoint(savepoint) } } override fun rollback() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("rollback", serviceHub) { delegate.rollback() } } override fun rollback(savepoint: Savepoint?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("rollback", serviceHub) { delegate.rollback(savepoint) } } - override fun setCatalog(catalog : String?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + override fun setCatalog(catalog: String?) { + restrictDatabaseOperationFromJdbcSession("setCatalog", serviceHub) { delegate.catalog = catalog } } override fun setTransactionIsolation(level: Int) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setTransactionIsolation", serviceHub) { delegate.transactionIsolation = level } } override fun setTypeMap(map: MutableMap>?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setTypeMap", serviceHub) { delegate.typeMap = map } } override fun setHoldability(holdability: Int) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setHoldability", serviceHub) { delegate.holdability = holdability } } override fun setSchema(schema: String?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setSchema", serviceHub) { delegate.schema = schema } } override fun setNetworkTimeout(executor: Executor?, milliseconds: Int) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setNetworkTimeout", serviceHub) { delegate.setNetworkTimeout(executor, milliseconds) } } override fun setAutoCommit(autoCommit: Boolean) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setAutoCommit", serviceHub) { delegate.autoCommit = autoCommit } } override fun setReadOnly(readOnly: Boolean) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.jdbcSession.") + restrictDatabaseOperationFromJdbcSession("setReadOnly", serviceHub) { delegate.isReadOnly = readOnly } } } \ No newline at end of file diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedDatabaseOperations.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedDatabaseOperations.kt new file mode 100644 index 0000000000..bc5cbc055f --- /dev/null +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedDatabaseOperations.kt @@ -0,0 +1,31 @@ +package net.corda.nodeapi.internal.persistence + +import net.corda.core.internal.PlatformVersionSwitches.RESTRICTED_DATABASE_OPERATIONS +import net.corda.core.internal.warnOnce +import net.corda.core.node.ServiceHub +import org.slf4j.LoggerFactory + +private val log = LoggerFactory.getLogger("RestrictedDatabaseOperations") + +internal inline fun restrictDatabaseOperationFromJdbcSession(method: String, serviceHub: ServiceHub, operation: () -> T): T { + return restrictDatabaseOperation("ServiceHub.jdbcSession.$method", serviceHub, operation) +} + +internal inline fun restrictDatabaseOperationFromEntityManager(method: String, serviceHub: ServiceHub, operation: () -> T): T { + return restrictDatabaseOperation("ServiceHub.withEntityManager.$method", serviceHub, operation) +} + +internal inline fun restrictDatabaseOperation(method: String, serviceHub: ServiceHub, operation: () -> T): T { + return if (serviceHub.getAppContext().cordapp.targetPlatformVersion >= RESTRICTED_DATABASE_OPERATIONS) { + throw UnsupportedOperationException("$method is restricted and cannot be called") + } else { + log.warnOnce( + "$method should not be called, as manipulating database transactions and connections breaks the Corda flow state machine in " + + "ways that only become evident in failure scenarios. Purely for API backwards compatibility reasons, the prior " + + "behaviour is continued for target platform versions less than $RESTRICTED_DATABASE_OPERATIONS. You should evolve " + + "the CorDapp away from using these problematic APIs as soon as possible. For target platform version of " + + "$RESTRICTED_DATABASE_OPERATIONS or above, an exception will be thrown instead." + ) + operation() + } +} \ No newline at end of file diff --git a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManager.kt b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManager.kt index 1ea4f2c4fd..d6d2672c0d 100644 --- a/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManager.kt +++ b/node-api/src/main/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManager.kt @@ -1,5 +1,6 @@ package net.corda.nodeapi.internal.persistence +import net.corda.core.node.ServiceHub import javax.persistence.EntityManager import javax.persistence.EntityTransaction import javax.persistence.LockModeType @@ -8,56 +9,59 @@ import javax.persistence.metamodel.Metamodel /** * A delegate of [EntityManager] which disallows some operations. */ -class RestrictedEntityManager(private val delegate: EntityManager) : EntityManager by delegate { +class RestrictedEntityManager(private val delegate: EntityManager, private val serviceHub: ServiceHub) : EntityManager by delegate { override fun getTransaction(): EntityTransaction { - return RestrictedEntityTransaction(delegate.transaction) + return RestrictedEntityTransaction(delegate.transaction, serviceHub) } override fun close() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("close", serviceHub) { delegate.close() } } override fun unwrap(cls: Class?): T { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + return restrictDatabaseOperationFromEntityManager("unwrap", serviceHub) { delegate.unwrap(cls) } } override fun getDelegate(): Any { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + return restrictDatabaseOperationFromEntityManager("getDelegate", serviceHub) { delegate.delegate } } override fun getMetamodel(): Metamodel? { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + return restrictDatabaseOperationFromEntityManager("getMetamodel", serviceHub) { delegate.metamodel } } override fun joinTransaction() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("joinTransaction", serviceHub) { delegate.joinTransaction() } } override fun lock(entity: Any?, lockMode: LockModeType?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.lock(entity, lockMode) } } override fun lock(entity: Any?, lockMode: LockModeType?, properties: MutableMap?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.lock(entity, lockMode, properties) } } override fun setProperty(propertyName: String?, value: Any?) { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("lock", serviceHub) { delegate.setProperty(propertyName, value) } } } -class RestrictedEntityTransaction(private val delegate: EntityTransaction) : EntityTransaction by delegate { +class RestrictedEntityTransaction( + private val delegate: EntityTransaction, + private val serviceHub: ServiceHub +) : EntityTransaction by delegate { override fun rollback() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("EntityTransaction.rollback", serviceHub) { delegate.rollback() } } override fun commit() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("EntityTransaction.commit", serviceHub) { delegate.commit() } } override fun begin() { - throw UnsupportedOperationException("This method cannot be called via ServiceHub.withEntityManager.") + restrictDatabaseOperationFromEntityManager("EntityTransaction.begin", serviceHub) { delegate.begin() } } } \ No newline at end of file diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnectionTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnectionTest.kt index 3708360bfc..39f2d7af73 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnectionTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedConnectionTest.kt @@ -1,104 +1,337 @@ package net.corda.nodeapi.internal.persistence import com.nhaarman.mockito_kotlin.mock +import com.nhaarman.mockito_kotlin.whenever +import net.corda.core.cordapp.Cordapp +import net.corda.core.cordapp.CordappContext +import net.corda.core.internal.PLATFORM_VERSION +import net.corda.core.node.ServiceHub import org.junit.Test import java.sql.Connection import java.sql.Savepoint class RestrictedConnectionTest { - private val connection : Connection = mock() - private val savePoint : Savepoint = mock() - private val restrictedConnection : RestrictedConnection = RestrictedConnection(connection) + private val connection: Connection = mock() + private val savePoint: Savepoint = mock() + private val cordapp = mock() + private val cordappContext = CordappContext.create(cordapp, null, javaClass.classLoader, mock()) + private val serviceHub = mock().apply { + whenever(getAppContext()).thenReturn(cordappContext) + } + private val restrictedConnection: RestrictedConnection = RestrictedConnection(connection, serviceHub) companion object { - private const val TEST_STRING : String = "test" - private const val TEST_INT : Int = 1 + private const val TEST_STRING: String = "test" + private const val TEST_INT: Int = 1 } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testAbort() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `abort with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.abort { println("I'm just an executor for this test...") } } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testClearWarnings() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `clearWarnings with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.clearWarnings() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testClose() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `close with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.close() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testCommit() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `commit with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.commit() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetSavepoint() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSavepoint with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.setSavepoint() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetSavepointWithName() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSavepoint with name with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.setSavepoint(TEST_STRING) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testReleaseSavepoint() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `releaseSavepoint with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.releaseSavepoint(savePoint) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testRollback() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `rollback with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.rollback() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testRollbackWithSavepoint() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `rollbackWithSavepoint with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.rollback(savePoint) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetCatalog() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setCatalog with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.catalog = TEST_STRING } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetTransactionIsolation() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setTransactionIsolation with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.transactionIsolation = TEST_INT } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetTypeMap() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setTypeMap with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) val map: MutableMap> = mutableMapOf() restrictedConnection.typeMap = map } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetHoldability() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setHoldability with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.holdability = TEST_INT } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetSchema() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSchema with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.schema = TEST_STRING } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetNetworkTimeout() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setNetworkTimeout with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetAutoCommit() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setAutoCommit with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedConnection.autoCommit = true } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetReadOnly() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setReadOnly with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) + restrictedConnection.isReadOnly = true + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `abort with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.abort { println("I'm just an executor for this test...") } + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `clearWarnings with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.clearWarnings() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `close with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.close() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `commit with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.commit() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSavepoint with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.setSavepoint() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSavepoint with name with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.setSavepoint(TEST_STRING) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `releaseSavepoint with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.releaseSavepoint(savePoint) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `rollback with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.rollback() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `rollbackWithSavepoint with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.rollback(savePoint) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setCatalog with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.catalog = TEST_STRING + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setTransactionIsolation with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.transactionIsolation = TEST_INT + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setTypeMap with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + val map: MutableMap> = mutableMapOf() + restrictedConnection.typeMap = map + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setHoldability with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.holdability = TEST_INT + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setSchema with target platform version of current 7 unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.schema = TEST_STRING + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setNetworkTimeout with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setAutoCommit with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.autoCommit = true + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setReadOnly with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedConnection.isReadOnly = true + } + + @Test(timeout = 300_000) + fun `abort with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.abort { println("I'm just an executor for this test...") } + } + + @Test(timeout = 300_000) + fun `clearWarnings with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.clearWarnings() + } + + @Test(timeout = 300_000) + fun `close with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.close() + } + + @Test(timeout = 300_000) + fun `commit with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.commit() + } + + @Test(timeout = 300_000) + fun `setSavepoint with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.setSavepoint() + } + + @Test(timeout = 300_000) + fun `setSavepoint with name with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.setSavepoint(TEST_STRING) + } + + @Test(timeout = 300_000) + fun `releaseSavepoint with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.releaseSavepoint(savePoint) + } + + @Test(timeout = 300_000) + fun `rollback with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.rollback() + } + + @Test(timeout = 300_000) + fun `rollbackWithSavepoint with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.rollback(savePoint) + } + + @Test(timeout = 300_000) + fun `setCatalog with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.catalog = TEST_STRING + } + + @Test(timeout = 300_000) + fun `setTransactionIsolation with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.transactionIsolation = TEST_INT + } + + @Test(timeout = 300_000) + fun `setTypeMap with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + val map: MutableMap> = mutableMapOf() + restrictedConnection.typeMap = map + } + + @Test(timeout = 300_000) + fun `setHoldability with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.holdability = TEST_INT + } + + @Test(timeout = 300_000) + fun `setSchema with target platform version of current 6 unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.schema = TEST_STRING + } + + @Test(timeout = 300_000) + fun `setNetworkTimeout with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.setNetworkTimeout({ println("I'm just an executor for this test...") }, TEST_INT) + } + + @Test(timeout = 300_000) + fun `setAutoCommit with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedConnection.autoCommit = true + } + + @Test(timeout = 300_000) + fun `setReadOnly with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) restrictedConnection.isReadOnly = true } } \ No newline at end of file diff --git a/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManagerTest.kt b/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManagerTest.kt index 6f53ade01c..92994a7fab 100644 --- a/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManagerTest.kt +++ b/node-api/src/test/kotlin/net/corda/nodeapi/internal/persistence/RestrictedEntityManagerTest.kt @@ -3,6 +3,10 @@ package net.corda.nodeapi.internal.persistence import com.nhaarman.mockito_kotlin.doReturn import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.whenever +import net.corda.core.cordapp.Cordapp +import net.corda.core.cordapp.CordappContext +import net.corda.core.internal.PLATFORM_VERSION +import net.corda.core.node.ServiceHub import org.junit.Test import javax.persistence.EntityManager import javax.persistence.EntityTransaction @@ -12,47 +16,160 @@ import kotlin.test.assertTrue class RestrictedEntityManagerTest { private val entitymanager = mock() private val transaction = mock() - private val restrictedEntityManager = RestrictedEntityManager(entitymanager) + private val cordapp = mock() + private val cordappContext = CordappContext.create(cordapp, null, javaClass.classLoader, mock()) + private val serviceHub = mock().apply { + whenever(getAppContext()).thenReturn(cordappContext) + } + private val restrictedEntityManager = RestrictedEntityManager(entitymanager, serviceHub) - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testClose() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `close with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedEntityManager.close() } @Test(timeout = 300_000) - fun testClear() { + fun `clear with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedEntityManager.clear() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testGetMetaModel() { - restrictedEntityManager.getMetamodel() + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `getMetaModel with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) + restrictedEntityManager.metamodel } @Test(timeout = 300_000) - fun testGetTransaction() { + fun `getTransaction with target platform version of current corda version executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) whenever(entitymanager.transaction).doReturn(transaction) assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testJoinTransaction() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `joinTransaction with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedEntityManager.joinTransaction() } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testLockWithTwoParameters() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `lock with two parameters with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testLockWithThreeParameters() { - val map: MutableMap = mutableMapOf() - restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC,map) + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `lock with three parameters with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) + val map: MutableMap = mutableMapOf() + restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map) } - @Test(expected = UnsupportedOperationException::class, timeout=300_000) - fun testSetProperty() { + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setProperty with target platform version of current corda version throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(PLATFORM_VERSION) + restrictedEntityManager.setProperty("number", 12) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `close with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.close() + } + + @Test(timeout = 300_000) + fun `clear with target platform version of 7 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.clear() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `getMetaModel with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.metamodel + } + + @Test(timeout = 300_000) + fun `getTransaction with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + whenever(entitymanager.transaction).doReturn(transaction) + assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `joinTransaction with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.joinTransaction() + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `lock with two parameters with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `lock with three parameters with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + val map: MutableMap = mutableMapOf() + restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map) + } + + @Test(expected = UnsupportedOperationException::class, timeout = 300_000) + fun `setProperty with target platform version of 7 throws unsupported exception`() { + whenever(cordapp.targetPlatformVersion).thenReturn(7) + restrictedEntityManager.setProperty("number", 12) + } + + @Test(timeout = 300_000) + fun `close with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedEntityManager.close() + } + + @Test(timeout = 300_000) + fun `clear with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedEntityManager.clear() + } + + @Test(timeout = 300_000) + fun `getMetaModel with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedEntityManager.metamodel + } + + @Test(timeout = 300_000) + fun `getTransaction with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + whenever(entitymanager.transaction).doReturn(transaction) + assertTrue(restrictedEntityManager.transaction is RestrictedEntityTransaction) + } + + @Test(timeout = 300_000) + fun `joinTransaction with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedEntityManager.joinTransaction() + } + + @Test(timeout = 300_000) + fun `lock with two parameters with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC) + } + + @Test(timeout = 300_000) + fun `lock with three parameters with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) + val map: MutableMap = mutableMapOf() + restrictedEntityManager.lock(Object(), LockModeType.OPTIMISTIC, map) + } + + @Test(timeout = 300_000) + fun `setProperty with target platform version of 6 executes successfully`() { + whenever(cordapp.targetPlatformVersion).thenReturn(6) restrictedEntityManager.setProperty("number", 12) } } \ No newline at end of file diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index 6b1f04410d..0dd5b5621d 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -1273,7 +1273,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, /** * Exposes the database connection as a [RestrictedConnection] to the users. */ - override fun jdbcSession(): Connection = RestrictedConnection(database.createSession()) + override fun jdbcSession(): Connection = RestrictedConnection(database.createSession(), services) @Suppress("TooGenericExceptionCaught") override fun withEntityManager(block: EntityManager.() -> T): T { @@ -1283,7 +1283,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, withSavePoint { savepoint -> // Restrict what entity manager they can use inside the block try { - block(RestrictedEntityManager(manager)).also { + block(RestrictedEntityManager(manager, services)).also { if (!manager.transaction.rollbackOnly) { manager.flush() } else { From a624e863fa67aff24a4272ae8635e139c9109c6f Mon Sep 17 00:00:00 2001 From: Ronan Browne Date: Tue, 22 Feb 2022 08:36:01 +0000 Subject: [PATCH 03/37] INFRA-1720: remove dockerhub publishing nightly (#7080) --- .ci/dev/publish-branch/Jenkinsfile.nightly | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.ci/dev/publish-branch/Jenkinsfile.nightly b/.ci/dev/publish-branch/Jenkinsfile.nightly index 4b331e9f5d..b7b36f7eb8 100644 --- a/.ci/dev/publish-branch/Jenkinsfile.nightly +++ b/.ci/dev/publish-branch/Jenkinsfile.nightly @@ -112,17 +112,6 @@ pipeline { ) } } - - stage('Publish Nightly to Docker Hub') { - steps { - withCredentials([ - usernamePassword(credentialsId: 'corda-publisher-docker-hub-credentials', - usernameVariable: 'DOCKER_USERNAME', - passwordVariable: 'DOCKER_PASSWORD')]) { - sh "./gradlew pushOfficialImages" - } - } - } } From beaed61028b1eee1c167d88ab190428786a38a86 Mon Sep 17 00:00:00 2001 From: Ronan Browne Date: Tue, 22 Feb 2022 08:36:33 +0000 Subject: [PATCH 04/37] INFRA-1720: remove dockerhub publishing nightly (#7081) --- .ci/dev/publish-branch/Jenkinsfile.nightly | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/.ci/dev/publish-branch/Jenkinsfile.nightly b/.ci/dev/publish-branch/Jenkinsfile.nightly index 4b331e9f5d..22466a4e69 100644 --- a/.ci/dev/publish-branch/Jenkinsfile.nightly +++ b/.ci/dev/publish-branch/Jenkinsfile.nightly @@ -113,16 +113,6 @@ pipeline { } } - stage('Publish Nightly to Docker Hub') { - steps { - withCredentials([ - usernamePassword(credentialsId: 'corda-publisher-docker-hub-credentials', - usernameVariable: 'DOCKER_USERNAME', - passwordVariable: 'DOCKER_PASSWORD')]) { - sh "./gradlew pushOfficialImages" - } - } - } } From 7658c5a4130eb3caaf1d57a677763da867ec7039 Mon Sep 17 00:00:00 2001 From: Ronan Browne Date: Tue, 22 Feb 2022 08:37:15 +0000 Subject: [PATCH 05/37] INFRA-1720: remove dockerhub publishing nightly (#7079) --- .ci/dev/publish-branch/Jenkinsfile.nightly | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.ci/dev/publish-branch/Jenkinsfile.nightly b/.ci/dev/publish-branch/Jenkinsfile.nightly index 4b331e9f5d..b7b36f7eb8 100644 --- a/.ci/dev/publish-branch/Jenkinsfile.nightly +++ b/.ci/dev/publish-branch/Jenkinsfile.nightly @@ -112,17 +112,6 @@ pipeline { ) } } - - stage('Publish Nightly to Docker Hub') { - steps { - withCredentials([ - usernamePassword(credentialsId: 'corda-publisher-docker-hub-credentials', - usernameVariable: 'DOCKER_USERNAME', - passwordVariable: 'DOCKER_PASSWORD')]) { - sh "./gradlew pushOfficialImages" - } - } - } } From a84c174aad1119dfc9013d721c528901a56b4cb8 Mon Sep 17 00:00:00 2001 From: Connel McGovern <100574906+mcgovc@users.noreply.github.com> Date: Tue, 15 Mar 2022 07:57:57 +0000 Subject: [PATCH 06/37] INFRA-1735 Teams notification's for C4 (#7111) * INFRA-1728 set correct java version for JDK 11 base image --- .ci/dev/compatibility/DockerfileJDK11 | 2 +- .ci/dev/publish-branch/Jenkinsfile.nightly | 24 ++++++++++++++++++++++ .ci/dev/regression/Jenkinsfile | 24 ++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/.ci/dev/compatibility/DockerfileJDK11 b/.ci/dev/compatibility/DockerfileJDK11 index 263c42a391..ff6eeaac95 100644 --- a/.ci/dev/compatibility/DockerfileJDK11 +++ b/.ci/dev/compatibility/DockerfileJDK11 @@ -1,4 +1,4 @@ -FROM azul/zulu-openjdk:11 +FROM azul/zulu-openjdk:11.0.14 RUN apt-get update && apt-get install -y curl apt-transport-https \ ca-certificates \ curl \ diff --git a/.ci/dev/publish-branch/Jenkinsfile.nightly b/.ci/dev/publish-branch/Jenkinsfile.nightly index 22466a4e69..d4be770a85 100644 --- a/.ci/dev/publish-branch/Jenkinsfile.nightly +++ b/.ci/dev/publish-branch/Jenkinsfile.nightly @@ -33,6 +33,18 @@ def nexusIqStageChoices = [nexusDefaultIqStage].plus( 'operate' ].minus([nexusDefaultIqStage])) +/** + * define an empty teamsWebHookURL and if it is a Release Branch + * then set it for the Corda 4 Jenkins Connector + */ +boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) +def teamsWebHookURL = "" +if (isReleaseBranch){ + withCredentials([string(credentialsId: 'ms-teams-webhook', variable: 'webhook_url')]) { + teamsWebHookURL = "$webhook_url" + } +} + pipeline { agent { label 'standard' } @@ -42,6 +54,18 @@ pipeline { overrideIndexTriggers(false) timeout(time: 3, unit: 'HOURS') buildDiscarder(logRotator(daysToKeepStr: '14', artifactDaysToKeepStr: '14')) + office365ConnectorWebhooks([[ + name : "Corda 4 Jenkins Connector", + notifyBackToNormal : true, + startNotification : false, + notifyFailure : true, + notifySuccess : true, + notifyNotBuilt : false, + notifyAborted : false, + notifyRepeatedFailure: true, + notifyUnstable : true, + url : "${teamsWebHookURL}" + ]]) } parameters { diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 13ef2be4c2..1fc0d187ed 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -7,6 +7,7 @@ /** * Sense environment */ +boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) boolean isReleaseTag = (env.TAG_NAME =~ /^release-.*(? Date: Tue, 15 Mar 2022 07:58:21 +0000 Subject: [PATCH 07/37] INFRA-1735 Teams notification's for C4 (#7109) * INFRA-1728 set correct java version for JDK 11 base image --- .ci/dev/compatibility/DockerfileJDK11 | 2 +- .ci/dev/publish-branch/Jenkinsfile.nightly | 23 +++++++++++++++++++++ .ci/dev/regression/Jenkinsfile | 24 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/.ci/dev/compatibility/DockerfileJDK11 b/.ci/dev/compatibility/DockerfileJDK11 index 263c42a391..ff6eeaac95 100644 --- a/.ci/dev/compatibility/DockerfileJDK11 +++ b/.ci/dev/compatibility/DockerfileJDK11 @@ -1,4 +1,4 @@ -FROM azul/zulu-openjdk:11 +FROM azul/zulu-openjdk:11.0.14 RUN apt-get update && apt-get install -y curl apt-transport-https \ ca-certificates \ curl \ diff --git a/.ci/dev/publish-branch/Jenkinsfile.nightly b/.ci/dev/publish-branch/Jenkinsfile.nightly index b7b36f7eb8..bfe370c88c 100644 --- a/.ci/dev/publish-branch/Jenkinsfile.nightly +++ b/.ci/dev/publish-branch/Jenkinsfile.nightly @@ -32,6 +32,17 @@ def nexusIqStageChoices = [nexusDefaultIqStage].plus( 'release', 'operate' ].minus([nexusDefaultIqStage])) +/** + * define an empty teamsWebHookURL and if it is a Release Branch + * then set it for the Corda 4 Jenkins Connector + */ +boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) +def teamsWebHookURL = "" +if (isReleaseBranch){ + withCredentials([string(credentialsId: 'ms-teams-webhook', variable: 'webhook_url')]) { + teamsWebHookURL = "$webhook_url" + } +} pipeline { agent { label 'standard' } @@ -42,6 +53,18 @@ pipeline { overrideIndexTriggers(false) timeout(time: 3, unit: 'HOURS') buildDiscarder(logRotator(daysToKeepStr: '14', artifactDaysToKeepStr: '14')) + office365ConnectorWebhooks([[ + name : "Corda 4 Jenkins Connector", + notifyBackToNormal : true, + startNotification : false, + notifyFailure : true, + notifySuccess : true, + notifyNotBuilt : false, + notifyAborted : false, + notifyRepeatedFailure: true, + notifyUnstable : true, + url : "${teamsWebHookURL}" + ]]) } parameters { diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 13ef2be4c2..1fc0d187ed 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -7,6 +7,7 @@ /** * Sense environment */ +boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) boolean isReleaseTag = (env.TAG_NAME =~ /^release-.*(? Date: Tue, 15 Mar 2022 14:56:48 +0000 Subject: [PATCH 08/37] INFRA-1735 Teams notification's for C4 (#7110) * INFRA-1728 set correct java version for JDK 11 base image --- .ci/dev/compatibility/DockerfileJDK11 | 2 +- .ci/dev/publish-branch/Jenkinsfile.nightly | 24 ++++++++++++++++++++++ .ci/dev/regression/Jenkinsfile | 24 ++++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/.ci/dev/compatibility/DockerfileJDK11 b/.ci/dev/compatibility/DockerfileJDK11 index 263c42a391..ff6eeaac95 100644 --- a/.ci/dev/compatibility/DockerfileJDK11 +++ b/.ci/dev/compatibility/DockerfileJDK11 @@ -1,4 +1,4 @@ -FROM azul/zulu-openjdk:11 +FROM azul/zulu-openjdk:11.0.14 RUN apt-get update && apt-get install -y curl apt-transport-https \ ca-certificates \ curl \ diff --git a/.ci/dev/publish-branch/Jenkinsfile.nightly b/.ci/dev/publish-branch/Jenkinsfile.nightly index b7b36f7eb8..0f38bf9cca 100644 --- a/.ci/dev/publish-branch/Jenkinsfile.nightly +++ b/.ci/dev/publish-branch/Jenkinsfile.nightly @@ -33,6 +33,18 @@ def nexusIqStageChoices = [nexusDefaultIqStage].plus( 'operate' ].minus([nexusDefaultIqStage])) +/** + * define an empty teamsWebHookURL and if it is a Release Branch + * then set it for the Corda 4 Jenkins Connector + */ +boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) +def teamsWebHookURL = "" +if (isReleaseBranch){ + withCredentials([string(credentialsId: 'ms-teams-webhook', variable: 'webhook_url')]) { + teamsWebHookURL = "$webhook_url" + } +} + pipeline { agent { label 'standard' } @@ -42,6 +54,18 @@ pipeline { overrideIndexTriggers(false) timeout(time: 3, unit: 'HOURS') buildDiscarder(logRotator(daysToKeepStr: '14', artifactDaysToKeepStr: '14')) + office365ConnectorWebhooks([[ + name : "Corda 4 Jenkins Connector", + notifyBackToNormal : true, + startNotification : false, + notifyFailure : true, + notifySuccess : true, + notifyNotBuilt : false, + notifyAborted : false, + notifyRepeatedFailure: true, + notifyUnstable : true, + url : "${teamsWebHookURL}" + ]]) } parameters { diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 13ef2be4c2..1fc0d187ed 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -7,6 +7,7 @@ /** * Sense environment */ +boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) boolean isReleaseTag = (env.TAG_NAME =~ /^release-.*(? Date: Tue, 15 Mar 2022 14:57:11 +0000 Subject: [PATCH 09/37] INFRA-1735 Teams notification's for C4 (#7112) * INFRA-1728 set correct java version for JDK 11 base image --- .ci/dev/regression/Jenkinsfile | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 13ef2be4c2..1fc0d187ed 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -7,6 +7,7 @@ /** * Sense environment */ +boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) boolean isReleaseTag = (env.TAG_NAME =~ /^release-.*(? Date: Wed, 16 Mar 2022 16:44:17 +0000 Subject: [PATCH 10/37] INFRA-1697 update wrapper URL --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 29c1f86072..0ebb3108e2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://gradleproxy:gradleproxy@software.r3.com/artifactory/gradle-proxy/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 5c83e27e78250d95c877f02e389058898af5157d Mon Sep 17 00:00:00 2001 From: Ronan Browne Date: Wed, 16 Mar 2022 16:44:17 +0000 Subject: [PATCH 11/37] INFRA-1697 update wrapper URL --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2e954d6bc7..74f4e46548 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ #Wed Aug 21 10:48:19 BST 2019 -distributionUrl=https\://gradleproxy:gradleproxy@software.r3.com/artifactory/gradle-proxy/gradle-5.4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStorePath=wrapper/dists From 21d768b0a3fdacbf148a78bf665745d8b8cc2052 Mon Sep 17 00:00:00 2001 From: Ronan Browne Date: Wed, 16 Mar 2022 16:51:07 +0000 Subject: [PATCH 12/37] INFRA-1699 use correct version --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 74f4e46548..4483da647f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ #Wed Aug 21 10:48:19 BST 2019 -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStorePath=wrapper/dists From a0aabe7b30b3407dbd70a37b4428b19dcb951c77 Mon Sep 17 00:00:00 2001 From: ConnelMcGovern Date: Tue, 22 Mar 2022 15:39:37 +0000 Subject: [PATCH 13/37] ENT-6716 Remove Corda OS image publishing to Docker hub for CE4.8.x patches and below --- .ci/dev/regression/Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 1fc0d187ed..f2e0df9d2d 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -11,6 +11,7 @@ boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) boolean isReleaseTag = (env.TAG_NAME =~ /^release-.*(? Date: Tue, 22 Mar 2022 15:40:44 +0000 Subject: [PATCH 14/37] ENT-6716 Remove Corda OS image publishing to Docker hub for CE4.8.x patches and below --- .ci/dev/regression/Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 1fc0d187ed..f2e0df9d2d 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -11,6 +11,7 @@ boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) boolean isReleaseTag = (env.TAG_NAME =~ /^release-.*(? Date: Tue, 22 Mar 2022 15:42:09 +0000 Subject: [PATCH 15/37] ENT-6716 Remove Corda OS image publishing to Docker hub for CE4.8.x patches and below --- .ci/dev/regression/Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 1fc0d187ed..f2e0df9d2d 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -11,6 +11,7 @@ boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) boolean isReleaseTag = (env.TAG_NAME =~ /^release-.*(? Date: Tue, 22 Mar 2022 15:43:33 +0000 Subject: [PATCH 16/37] ENT-6716 Remove Corda OS image publishing to Docker hub for CE4.8.x patches and below --- .ci/dev/regression/Jenkinsfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 1fc0d187ed..f2e0df9d2d 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -11,6 +11,7 @@ boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) boolean isReleaseTag = (env.TAG_NAME =~ /^release-.*(? Date: Wed, 23 Mar 2022 16:53:09 +0000 Subject: [PATCH 17/37] INFRA-1743 Activate C4 email notifications Open source and Ent --- .ci/dev/regression/Jenkinsfile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 1fc0d187ed..42d0f34a7c 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -382,6 +382,22 @@ pipeline { } } } + failure { + script { + def statusSymbol = '\u274c' + if (isReleaseTag || isReleaseBranch || isReleaseCandidate) { + emailext subject: "$statusSymbol " + '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', + body: '${SCRIPT, template="groovy-html.template"}', + recipientProviders: [ + [$class: 'CulpritsRecipientProvider'], + [$class: 'RequesterRecipientProvider'] + ], + mimeType: 'text/html', + replyTo: '$DEFAULT_REPLYTO', + to: "adel.el-beik@r3.com" + } + } + } cleanup { deleteDir() /* clean up our workspace */ } From 682aa43f97b019591034f4108622e4e000edb7ad Mon Sep 17 00:00:00 2001 From: ConnelMcGovern Date: Wed, 23 Mar 2022 16:54:21 +0000 Subject: [PATCH 18/37] INFRA-1743 Activate C4 email notifications Open source and Ent --- .ci/dev/regression/Jenkinsfile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 1fc0d187ed..42d0f34a7c 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -382,6 +382,22 @@ pipeline { } } } + failure { + script { + def statusSymbol = '\u274c' + if (isReleaseTag || isReleaseBranch || isReleaseCandidate) { + emailext subject: "$statusSymbol " + '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', + body: '${SCRIPT, template="groovy-html.template"}', + recipientProviders: [ + [$class: 'CulpritsRecipientProvider'], + [$class: 'RequesterRecipientProvider'] + ], + mimeType: 'text/html', + replyTo: '$DEFAULT_REPLYTO', + to: "adel.el-beik@r3.com" + } + } + } cleanup { deleteDir() /* clean up our workspace */ } From b03e71cb536529faad5b0c74525d45f86be1f9ef Mon Sep 17 00:00:00 2001 From: ConnelMcGovern Date: Wed, 23 Mar 2022 16:56:35 +0000 Subject: [PATCH 19/37] INFRA-1743 Activate C4 email notifications Open source and Ent --- .ci/dev/regression/Jenkinsfile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 1fc0d187ed..42d0f34a7c 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -382,6 +382,22 @@ pipeline { } } } + failure { + script { + def statusSymbol = '\u274c' + if (isReleaseTag || isReleaseBranch || isReleaseCandidate) { + emailext subject: "$statusSymbol " + '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', + body: '${SCRIPT, template="groovy-html.template"}', + recipientProviders: [ + [$class: 'CulpritsRecipientProvider'], + [$class: 'RequesterRecipientProvider'] + ], + mimeType: 'text/html', + replyTo: '$DEFAULT_REPLYTO', + to: "adel.el-beik@r3.com" + } + } + } cleanup { deleteDir() /* clean up our workspace */ } From 9e99af2355df53b8a69c20a099cc40ea7b7aad94 Mon Sep 17 00:00:00 2001 From: Adel El-Beik Date: Wed, 30 Mar 2022 16:35:40 +0100 Subject: [PATCH 20/37] CORDA-4239: Regenerate test certificates with 10yr validity. --- .../internal/crypto/keystores/bridge_ec.jks | Bin 1163 -> 1162 bytes .../internal/crypto/keystores/bridge_rsa.jks | Bin 1803 -> 1804 bytes .../internal/crypto/keystores/float_ec.jks | Bin 1161 -> 1160 bytes .../internal/crypto/keystores/float_rsa.jks | Bin 1802 -> 1804 bytes .../internal/crypto/keystores/gencerts.sh | 40 ++++++++++++++++++ .../internal/crypto/keystores/trust.jks | Bin 502 -> 502 bytes 6 files changed, 40 insertions(+) create mode 100755 node-api/src/test/resources/net/corda/nodeapi/internal/crypto/keystores/gencerts.sh diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/crypto/keystores/bridge_ec.jks b/node-api/src/test/resources/net/corda/nodeapi/internal/crypto/keystores/bridge_ec.jks index 2e74e4d29301ae96e90d0149d50817f7667c816a..f0a6921cff2767ab695f478ef30aa1e96519db64 100644 GIT binary patch delta 699 zcmeC??BbjtUtfPa<@ad@28McrS_3{dE^RhO7Dg>5K}JSa2A1qkjnP-mzm&GVDtX)F zUgq38t9A)=tTLXt#js|Q@vSq}%v;V(cei^nN%EGC*rYYn&SgGLIw9CywC3oSb8FA- z3vqlDrf_`yBGJYzg%Zz?v|IO|X)B+S%Ay{+*0rg0c}7~jSF)P6`7D=Gn;ij1q=9Z= zVqlHXGc~YeU|{@X(8Txyi03X~W@2PwV&SiwojLg;Q;f8ck%6(XfuX6Psew_HIIl5~ zYh(`LPIh3-NL60px9QgUTiK5TB=?95^x2)Gp6BVfl05JxWHf&>g_de}x#z{tP@#>CVT zIbcBC$@iJOCr@FPa`=!bcvWHg?Mdpd^w!*}iEV7(8!4s#TI9^_>Sb;7TYO(xUK2m{ zMMs~@zjLNktahhFEc+^znwbxcud>dYV*G2(iplSoW$Uqp2%5(|7z|vQ6d7KntY*5r z?@v727yi$0l51qvWF@+H6y>vtc&;;>R1*7*Nx`A_m-I!uW6P>l1&ik%JyYVc(Ep*P mw~#?@(am3>Mwg~Yy;)GC{><#!vhRzV4}6%@e%?cau^Rwg*%&nd delta 682 zcmeC;?B<*xU!VDC!Hl^K3=H)KwFZ1_T-t1mER0%Af{cu;3@q8TAt}6y))zu%9q@kL zvf9dH!cmF!QnR1RX#II{X5TAYM{{kydy6tNL>g_J#EivvzcrkESBItj^w$Y?mCTb@ zp4#s|ce;M_E`Bblsk>IJTDg+nfp_a>34R{YFKim(_i|p`n9{9Xc$vAUHP*+S4d@0Y z2G$5YQv*u|2FAYzO^iQ*cH;z9{X}kBO_TK210M*CKG` z?uWTr-X>2D%(K|1Gw%Rf-7ifyu9HIQW{V3A@(twKm_uciStJa^8bmg0Nr*Ju_sWvF z{lhWtOeS761l3Y#dr`9_MUXn3-4^m^~N_T$vQy^#Ybk z%4eH4O_;>%FZtj#gPU<#mt^HH&Ob`JE?wR)m=qZ%FOLnn$W-cdEB)M=uL~qU?^$do oGW*+^8~5(JS5+Ol`E|QOt50`j&*gJMLGyCl7bLIwW63BA0Gz)Nr2qf` diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/crypto/keystores/bridge_rsa.jks b/node-api/src/test/resources/net/corda/nodeapi/internal/crypto/keystores/bridge_rsa.jks index ed41a57d6a8d1167f61d9a668328947839b5ece4..87224d4727e13e635b4eb1d20c0a85eaa3d0e890 100644 GIT binary patch delta 1351 zcmeC?>*1RqUtfPapCZ=r$d~96WY>X_7T1ptx zjAT;EjtTbuui9+#XS|8`>hIUB zTTd-n{+*-H;bVfOqG}{-{azo9e`1eA`%ho4$^IL@>G-L&X>6>#1>BG1o^$i@iQ1L8 z?f(+FpzK0n*3KIrcVxSqc$U|2d)cK0)3@@b9Ld)T`PJs2t^1zyZnskBfvek86H>#4 z!`uBLH_AFTx>`K@`|9B5HO1u~Hb!^n8P-=_s@kO`xOLU~yE{0;&-wZ5?}@6f^qSUf z?IgHr<-$Fz?-f^M-VHJMxoXShaN>R!3#pmCs(bnu8tHE~K3#uGPj=BGrwy!82ymhC%_tvrn0dhIt z7?K5ZOMNW%*ZCgu`C&3e>HS^D_PR;VN3Q%6DE=$Y#*#F<-Qq>Wa@EEy-;c2H?Ws6u zR(sB9!O5B7zZ+k-I5(K8UEch@ZKZ=!h1(P!(~WE!XD!-uNZnx8yxLdO5Ak-&z4h-u zBC)SADa)hJ+)umsOz(a^Cx%_0y(QnU{QcMZz|*XP!RAh~RPhV(^r?P{P7@bBS!Nkw zAzg8P{$+E4SdHVC6dtW?mR-vB;(^k=I}VlI-3-7q%)lCg2N85kQI7@8WI8W=~3^BM!WM&?kif!E|jR+Gsan2qaaYMk>B z`Bv1iQ?PRSmo0Lqy+byJezi@NPkw!0V^yuryXY5l)cJ4m&-`+W&uRYjn}Up}6HOC|=U4u@lmx~A-E+r3GNLs_|Pr^$y8T2F$eDonm6#8R1= zTphs@%Au#=c>ZX?Yu-ABH(M_Bdo2%mr?2hK#LURRxVX?D-$0&?IaF4eMZ!R=L8K`r z?)dcc4`od+XFOoJH<|lSbZp<`UKXqR?+(fbA1k`%x4!7jU#_<8%;vUFdImgf99nH2 z=WJP+nOGT^-5CsAm=w}ami;xd%a2WrU$47#^|qiL-!d(CF4N`Px8wQaS+|V%oWQmD^sZPDkWl7K58DU| zWf^!Vo0wW6hcbveS%BGlvIv`$!-q`4s|wR^Pf~xSx8_z&Y-9W0NGbi-B4=(_FKe6M z;`_?-n)si%u8~=jmFV74l+PyOxz21-N$fW!1&7{W(iiQHEvr@)ES`Jx uOo_`v|A(61LI$}-H-Cj1U7GTB>E!M$-}BBEU%$TU#`BGz)f0LccLD$-c}zV3 delta 1334 zcmV-61FY5{+= zcoAM{K}#-<-dj4*Fw#Yi+0A?U1HMQ4SZF zS*dYQ%>{9R^H>eB&9N8?f zpRE0e2W`3AsjeN{Mx<$N0Hv~26K`eGR2l^mc6zxyAbp1UPoyMhGc4MZBBe5TwvPpU z#BdqK;sBQP zd@Ryo??9;=mGsm|;$h2*0Jt|w{zdocc&S5+ENkvBCkG5@Mw+9KoTM|qPL_@`AexY{ zMn#rqo!`u9gMFz9&jijX-7dO-aobXIGO$3eY~ zh!#x28Tsk}DM4Syp&dN=O9WLZxo*kaecT9Mjg76rkOA)1teQ7PR=zR4G{0Jc00002 z00mesH842<00KlXf&xG=f&t{90|Eg80t7*I5rr@e1_&yKNX|V30|EsAFi0^AFbM_& zRg)V7MH?|WFf=eTFgZ0gGBjEj4KX<|H!w0VIW;yiG?RM+YJZ~@=@sV|Yu1&gK;lyd zWKDVg<|!vZ4@O6t~oPTFrX~5RrutoVjpgU_}%^ zRBe@{^ldz_TPsNd0|5X5qj4~AFdqg3RUIP)7%&!q6tgNA6oB7KY8>0_Kbj1=Hh=Ej zAYr#0aOs9wA7O9&hV4(yYl1{7i-87bIHU9`l_S!(64@`xYlMTXcw zN~J|4fOtWPTU~_00wDm;TE}pznSe-D@t1t+yb&}vXqO4i#r~|sI1Y%gx_Iya1z0XM zFgXAK0l6@O0ktrK0a>5}0s#U71Q^Pp6q5u4TpTeuFf=eTFgZ0eFgaQm4Kgt?GBP+Y zIW;seIa-ro1xu3^1{y%p|8JeG<%+v5`}Jl4+O&ibz39~RlanalTYVwp5EOYu)lzRk z6$va(Q5t7o#unztoV~jI%rN2BrU2AO`+LO*we)5%<9B2!Vx+y^35(uzyJUM diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/crypto/keystores/float_ec.jks b/node-api/src/test/resources/net/corda/nodeapi/internal/crypto/keystores/float_ec.jks index c08d825b2f397a3784f85f49c4cbe7e178f4006c..bd7f2632260038e51f81b52a96be20eb1b8d9505 100644 GIT binary patch delta 677 zcmeC=?BJXrS6_cSmC=`hfuY`@)_{+VOPh_6g;9%1kdcvt|Gp*^HR&0UBm5jWFo3%H22v%T|V4%`P!wkr&2T@?UxVTf0KFD@AoO~ zwH4cZr{}t8EQ{Lu=jz_1|3$ktC>k+sik9E*pk!gW=Z)|_OFnJOy}j4Z)E_e61at!v z18anysevT}1LJRlCdThTJZAwj6C)E7i?OEOx5?+3Vx*0X42+Ep3{4G94UD72d5wWw zBXbCMvOQyZ>VYuPx}N-7vLf&8Hsb4aC3{}lEu(9nxdv8!Gz`h)6j@6|#4pY-|p zd6l9KI&0K@G`+N?ZLbwJmlR2T?RHpPXpnCp&&C`otIQ%{Al4w#6ccxR`uT^lrk67w zu-u!>{Uz=W7YJu)s`1u?egZ>ToUYdOmMPMm%}Z|xBr+FD!i_7@AtM^#?>-n`^IR!sZ>gNTJPkIOj0bI>0ui|K_CMU0uxh9CD<;2TmaWI;cQh}0Fc`QpDKflDSq5nfoZy|%+qMN@$jV?`* auz2KqeUtPTGn>4VZ?3K>G1#rZm5K}JSa29|7fZm09V8v1npPE*~n z^y#r9R&Q@Kd)?>0u*y-yO-xVo&U^qjS3s^Nl`HyS@xo}Zt+{e@VNTn~e|c9eTtZ{?&7(Pw~e zU}9j6&@(l#WME+YW6;F-1BmA=U}j=uVq!^pd}`w4b4)SPhL#2<2F3=Krsf9bQR2Kn zuDO8`gge=uF+Fub*st3k1U}7MQZp}Gt$5Pc)X42;{BJ9~`6U%H-JHo{c$FR+&Y@K&(MzvzCNN!+ozT zncHvdXYuSbtABU*@nmi$s~n-enh!+`oAq6iMJ1M%F#GlYJ;Q9k!^WZ2=5fxJg_((! zf!Tw>z?DgnVF!cL#>p#hpGdlVl-+-R+$EGH?jGUwA>FGIt^vCace&0X8pXZyUaY-Y`6oMpSh*=m6 zXaSRfCQt*dYK4X);dnq34oAU|$v~CQ`K0i&MstOxyFx0iuIQ)aALXgXtX`+=dQp>H zSLL5a&r;d#MyZxJU(Zb2w0rcF$q4EiPaw2TvJMqX=&tz!CLS|c&%&H(L7cPr>-Ptf zQ$cfarPg~-WAHu!#XS_*D3sPdVMtscHf>_#bSH53T{89!N0 z?cV1e�?_{5(kI3ArSt=N_t#dLDFYR{A^e)p16)ZlfV&>b{hduiz!IkEKqQWS+*l z%$7zvP<3%1%??d-SIJj?*-4Pg#UBcnHauaZ`2G|`Eo#{DIjf;#(H8#1v8=yExrzN& zmkTZ3bgmcnD&LCy6V|-=2mv?F9mh>FF2@&8=H?~jg;S3Vv2im2i^iUweYJr-zjal= zv8Xz+NumzL3YDfJoBX%kMs`iq6OHQp%HuhrP!h!KBHrutMvQSPa6K%2avWIWc-rLikh$f4c*4HJV*#>`f|q^; zHO&!L_Bb=e&0(pIs!j?CW5KCTd*0x-eA~wbF4VRy_Lxul~L^gN=z$LJn7^vbjKf@x<_*-hx8Z!j<06%h8-3`R7l9OH)GuVb7Vp zu^+lkYi;n@p*uPxXZh6(d0SLuwU2h+O>`^T^jgW<1{qdc|MAR33qM(%`Ovo2?(A^;Q&L4tvvzz?tq*QWp{?`64!Ua&22m!%>r z{3D-XZTXHCMA(}j<*EXhZ*D6{k)%{wH*)U5V!UyzA3|- z*M)DbU!dAoW|iZI1Yej6M(XO)pRNnRXi1@0qu@RrSr}8_}#X4QNXBn-lqCc0;JLJUc~09WN4%g}z7f z{pQn0uL6U2S3}VAm^oQ!qDjMvBVHHJMxk}c*LQGZXp4Zk8(U#4CU(}I-=Y~^+R+=c or_y)K(pw9RJUgNYAPnSD37&X`(}vouvm%jchPuGG(gsfa4~lwLZU6uP delta 1349 zcmZwFc{r2_90%}u=VD?88OMZiu4N2fgB+DgCKYRp;|Y@_MX7dn))6D7#;u6nT$5uc z%dSvFm`deXxkjiQ4IvYeoE*}Y*fz<_s0Tbu@g!HMs)8r*j z2vLWEu!6)+8nl;V!_&{r&0y=w#^Wyc2l{%5mnIvfGs}p`e&><{NAvd+N;%lkin&4egU2HLJ~h9%+rL;KlhpU%S-w2#T?EXnY_z_KMPCl6 z*Ho?xJxk#f5{&$V%=c&h?U%Fir>8zU_0by#5cj5{@UjWMU6Rhh&pJi&1#wxR;N!)q@5RlU9MBsPtHUx+1$ZYW9o}|o*plmEN@S5ENXfur`^3QVDq}!A+L+a zT^73G&4!ulr8kxMd^VqaV&Z8vOtN7Z%FDzOw2^%Fk~Q0bTws!qfCF$i@{k5b2+E?R zNeTOUb|4XO6b#&FCIe#75CP$+W@ZCgfaai$rIoq0j|x^2tw7562t^@Ia_-=&@E_xh ztqP7C->!9B8_2dcOjt~95$$6bweJ|L?7u`jQNT~wVe7QM=#*M7F*d$k64@iw%t#2S6j!Ot}fy&M#4>G@bK)LfnjqudaMXG|z=kYZpRs8v}1HtMeb31vm z4O=<$qDd$XY0G&ywsuU6i=3I~RqK!qBHex^RVV+qJ;D(NI>5EUkgWMoY7}WsLbF*Bo3tR=kvM(7C22~t9D+12-znO`xL zA~5-9H4qrS6Q^*0dSC^D48|DI+LQA5Na`~;=58en*@eC($gfRV+@5#8@k00FzmhWA+!(aQ*H8?uv$YwttTJ2K`?YMb#yzFZRRwt(FqlYG`aP}MA C root.pem +keytool -importcert -noprompt -file root.pem -alias root -keystore trust.jks -storepass trustpass + +# Create a chain for EC Bridge +keytool -certreq -alias bridgecert -keystore bridge_ec.jks -storepass bridgepass -keypass bridgepass |keytool -gencert -validity 3650 -ext ku:c=dig,keyEncipherment -ext: eku:true=serverAuth,clientAuth -rfc -keystore floatca.jks -alias floatroot -storepass capass -keypass cakeypass > bridge_ec.pem +cat root.pem bridge_ec.pem >> bridgechain_ec.pem +keytool -importcert -noprompt -file bridgechain_ec.pem -alias bridgecert -keystore bridge_ec.jks -storepass bridgepass -keypass bridgepass + +# Create a chain for RSA Bridge +keytool -certreq -alias bridgecert -keystore bridge_rsa.jks -storepass bridgepass -keypass bridgepass |keytool -gencert -validity 3650 -ext ku:c=dig,keyEncipherment -ext: eku:true=serverAuth,clientAuth -rfc -keystore floatca.jks -alias floatroot -storepass capass -keypass cakeypass > bridge_rsa.pem +cat root.pem bridge_rsa.pem >> bridgechain_rsa.pem +keytool -importcert -noprompt -file bridgechain_rsa.pem -alias bridgecert -keystore bridge_rsa.jks -storepass bridgepass -keypass bridgepass + +# Create a chain for EC Float +keytool -certreq -alias floatcert -keystore float_ec.jks -storepass floatpass -keypass floatpass |keytool -gencert -validity 3650 -ext ku:c=dig,keyEncipherment -ext: eku::true=serverAuth,clientAuth -rfc -keystore floatca.jks -alias floatroot -storepass capass -keypass cakeypass > float_ec.pem +cat root.pem float_ec.pem >> floatchain_ec.pem +keytool -importcert -noprompt -file floatchain_ec.pem -alias floatcert -keystore float_ec.jks -storepass floatpass -keypass floatpass + +# Create a chain for RSA Float +keytool -certreq -alias floatcert -keystore float_rsa.jks -storepass floatpass -keypass floatpass |keytool -gencert -validity 3650 -ext ku:c=dig,keyEncipherment -ext: eku::true=serverAuth,clientAuth -rfc -keystore floatca.jks -alias floatroot -storepass capass -keypass cakeypass > float_rsa.pem +cat root.pem float_rsa.pem >> floatchain_rsa.pem +keytool -importcert -noprompt -file floatchain_rsa.pem -alias floatcert -keystore float_rsa.jks -storepass floatpass -keypass floatpass diff --git a/node-api/src/test/resources/net/corda/nodeapi/internal/crypto/keystores/trust.jks b/node-api/src/test/resources/net/corda/nodeapi/internal/crypto/keystores/trust.jks index b4ebeb70fc3f546a9d4694440ccc216f124ff4be..1252f7002a7c6a130c76ac3be08322e7eecdcb05 100644 GIT binary patch delta 257 zcmV+c0sj8>1NH-u83ljaWccfm9vTD*XI8P1JX{Fhv3(0P19`0@J?yUk3CK^Xy}M9IR?#M~HH71{6uIHj;E* z_5vV4jrtqWKE|edB@uI-#msa>p-1NH-u83k$LpXF(h9vTD~%ApjIJX{in}iR^=1Luw1g48=+yL+lPKR?eIerz6nRC}Qg1;O z2`o-g8fRa|7UsyDy}JC&FyYpxn1061pN^AR0Udv{Di{=i-%4s6+w4D@47oOc?%m@s z3Fhv3&M=nsM86Rskf{>C8PZ{9r07f%*iWzzO3H%~0M2bu3 z0wDmCr(IIf0(C;#XU@#^pc(VLqdpXy_RQGc-$#0S!rAqf8jiPF0R|#rr==1{ Date: Tue, 5 Apr 2022 14:31:17 +0100 Subject: [PATCH 21/37] NOTICK: Reverted file in merge. --- .ci/dev/publish-branch/Jenkinsfile.nightly | 35 +++++++++++++++------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/.ci/dev/publish-branch/Jenkinsfile.nightly b/.ci/dev/publish-branch/Jenkinsfile.nightly index 4b331e9f5d..0f38bf9cca 100644 --- a/.ci/dev/publish-branch/Jenkinsfile.nightly +++ b/.ci/dev/publish-branch/Jenkinsfile.nightly @@ -33,6 +33,18 @@ def nexusIqStageChoices = [nexusDefaultIqStage].plus( 'operate' ].minus([nexusDefaultIqStage])) +/** + * define an empty teamsWebHookURL and if it is a Release Branch + * then set it for the Corda 4 Jenkins Connector + */ +boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) +def teamsWebHookURL = "" +if (isReleaseBranch){ + withCredentials([string(credentialsId: 'ms-teams-webhook', variable: 'webhook_url')]) { + teamsWebHookURL = "$webhook_url" + } +} + pipeline { agent { label 'standard' } @@ -42,6 +54,18 @@ pipeline { overrideIndexTriggers(false) timeout(time: 3, unit: 'HOURS') buildDiscarder(logRotator(daysToKeepStr: '14', artifactDaysToKeepStr: '14')) + office365ConnectorWebhooks([[ + name : "Corda 4 Jenkins Connector", + notifyBackToNormal : true, + startNotification : false, + notifyFailure : true, + notifySuccess : true, + notifyNotBuilt : false, + notifyAborted : false, + notifyRepeatedFailure: true, + notifyUnstable : true, + url : "${teamsWebHookURL}" + ]]) } parameters { @@ -112,17 +136,6 @@ pipeline { ) } } - - stage('Publish Nightly to Docker Hub') { - steps { - withCredentials([ - usernamePassword(credentialsId: 'corda-publisher-docker-hub-credentials', - usernameVariable: 'DOCKER_USERNAME', - passwordVariable: 'DOCKER_PASSWORD')]) { - sh "./gradlew pushOfficialImages" - } - } - } } From 6d2a9931af167e7846613b073d6200de4fe5e233 Mon Sep 17 00:00:00 2001 From: Adel El-Beik Date: Tue, 5 Apr 2022 18:07:25 +0100 Subject: [PATCH 22/37] NOTICK: Reverted Jenkins.nightly. --- .ci/dev/publish-branch/Jenkinsfile.nightly | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.ci/dev/publish-branch/Jenkinsfile.nightly b/.ci/dev/publish-branch/Jenkinsfile.nightly index 1ab8353624..bfe370c88c 100644 --- a/.ci/dev/publish-branch/Jenkinsfile.nightly +++ b/.ci/dev/publish-branch/Jenkinsfile.nightly @@ -44,18 +44,6 @@ if (isReleaseBranch){ } } -/** - * define an empty teamsWebHookURL and if it is a Release Branch - * then set it for the Corda 4 Jenkins Connector - */ -boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) -def teamsWebHookURL = "" -if (isReleaseBranch){ - withCredentials([string(credentialsId: 'ms-teams-webhook', variable: 'webhook_url')]) { - teamsWebHookURL = "$webhook_url" - } -} - pipeline { agent { label 'standard' } From 56581b340a4ac703fb8411d1ee6a34ca0238d1f4 Mon Sep 17 00:00:00 2001 From: Connel McGovern <100574906+mcgovc@users.noreply.github.com> Date: Mon, 9 May 2022 13:15:27 +0100 Subject: [PATCH 23/37] INFRA-1743 Slack & E-mail notification --- .ci/dev/regression/Jenkinsfile | 55 +++++++++++----------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index d24250c6b7..e28197963d 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -3,6 +3,7 @@ * Jenkins pipeline to build Corda OS release branches and tags. * PLEASE NOTE: we DO want to run a build for each commit!!! */ +@Library('corda-shared-build-pipeline-steps') /** * Sense environment @@ -41,17 +42,6 @@ def nexusIqStageChoices = [nexusDefaultIqStage].plus( 'operate' ].minus([nexusDefaultIqStage])) -/** - * define an empty teamsWebHookURL and if it is a Release Branch - * then set it for the Corda 4 Jenkins Connector - */ -def teamsWebHookURL = "" -if (isReleaseBranch || isReleaseTag){ - withCredentials([string(credentialsId: 'ms-teams-webhook', variable: 'webhook_url')]) { - teamsWebHookURL = "$webhook_url" - } -} - /** * Common Gradle arguments for all Gradle executions */ @@ -74,18 +64,6 @@ pipeline { parallelsAlwaysFailFast() timeout(time: 6, unit: 'HOURS') timestamps() - office365ConnectorWebhooks([[ - name : "Corda 4 Jenkins Connector", - notifyBackToNormal : true, - startNotification : false, - notifyFailure : true, - notifySuccess : true, - notifyNotBuilt : false, - notifyAborted : false, - notifyRepeatedFailure: true, - notifyUnstable : true, - url : "${teamsWebHookURL}" - ]]) } parameters { @@ -102,6 +80,7 @@ pipeline { CORDA_ARTIFACTORY_PASSWORD = "${env.ARTIFACTORY_CREDENTIALS_PSW}" CORDA_ARTIFACTORY_USERNAME = "${env.ARTIFACTORY_CREDENTIALS_USR}" DOCKER_URL = "https://index.docker.io/v1/" + EMAIL_RECIPIENTS = credentials('corda4-email-recipient') } stages { @@ -383,21 +362,23 @@ pipeline { } } } + success { + script { + sendSlackNotifications("good", "BUILD PASSED", false, "#corda-corda4-open-source-build-notifications") + } + } + unstable { + script { + sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", false, "#corda-corda4-open-source-build-notifications") + } + } failure { - script { - def statusSymbol = '\u274c' - if (isReleaseTag || isReleaseBranch || isReleaseCandidate) { - emailext subject: "$statusSymbol " + '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', - body: '${SCRIPT, template="groovy-html.template"}', - recipientProviders: [ - [$class: 'CulpritsRecipientProvider'], - [$class: 'RequesterRecipientProvider'] - ], - mimeType: 'text/html', - replyTo: '$DEFAULT_REPLYTO', - to: "adel.el-beik@r3.com" - } - } + script { + sendSlackNotifications("danger", "BUILD FAILURE", true, "#corda-corda4-open-source-build-notifications") + if (isReleaseTag || isReleaseBranch || isReleaseCandidate) { + sendEmailNotifications("${env.EMAIL_RECIPIENTS}") + } + } } cleanup { deleteDir() /* clean up our workspace */ From 5149889b34c2dd2eb3104ec2f7dddb869f4e5abc Mon Sep 17 00:00:00 2001 From: Connel McGovern <100574906+mcgovc@users.noreply.github.com> Date: Mon, 9 May 2022 13:16:38 +0100 Subject: [PATCH 24/37] INFRA-1743 Slack & E-mail notification --- .ci/dev/regression/Jenkinsfile | 55 +++++++++++----------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index d24250c6b7..e28197963d 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -3,6 +3,7 @@ * Jenkins pipeline to build Corda OS release branches and tags. * PLEASE NOTE: we DO want to run a build for each commit!!! */ +@Library('corda-shared-build-pipeline-steps') /** * Sense environment @@ -41,17 +42,6 @@ def nexusIqStageChoices = [nexusDefaultIqStage].plus( 'operate' ].minus([nexusDefaultIqStage])) -/** - * define an empty teamsWebHookURL and if it is a Release Branch - * then set it for the Corda 4 Jenkins Connector - */ -def teamsWebHookURL = "" -if (isReleaseBranch || isReleaseTag){ - withCredentials([string(credentialsId: 'ms-teams-webhook', variable: 'webhook_url')]) { - teamsWebHookURL = "$webhook_url" - } -} - /** * Common Gradle arguments for all Gradle executions */ @@ -74,18 +64,6 @@ pipeline { parallelsAlwaysFailFast() timeout(time: 6, unit: 'HOURS') timestamps() - office365ConnectorWebhooks([[ - name : "Corda 4 Jenkins Connector", - notifyBackToNormal : true, - startNotification : false, - notifyFailure : true, - notifySuccess : true, - notifyNotBuilt : false, - notifyAborted : false, - notifyRepeatedFailure: true, - notifyUnstable : true, - url : "${teamsWebHookURL}" - ]]) } parameters { @@ -102,6 +80,7 @@ pipeline { CORDA_ARTIFACTORY_PASSWORD = "${env.ARTIFACTORY_CREDENTIALS_PSW}" CORDA_ARTIFACTORY_USERNAME = "${env.ARTIFACTORY_CREDENTIALS_USR}" DOCKER_URL = "https://index.docker.io/v1/" + EMAIL_RECIPIENTS = credentials('corda4-email-recipient') } stages { @@ -383,21 +362,23 @@ pipeline { } } } + success { + script { + sendSlackNotifications("good", "BUILD PASSED", false, "#corda-corda4-open-source-build-notifications") + } + } + unstable { + script { + sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", false, "#corda-corda4-open-source-build-notifications") + } + } failure { - script { - def statusSymbol = '\u274c' - if (isReleaseTag || isReleaseBranch || isReleaseCandidate) { - emailext subject: "$statusSymbol " + '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', - body: '${SCRIPT, template="groovy-html.template"}', - recipientProviders: [ - [$class: 'CulpritsRecipientProvider'], - [$class: 'RequesterRecipientProvider'] - ], - mimeType: 'text/html', - replyTo: '$DEFAULT_REPLYTO', - to: "adel.el-beik@r3.com" - } - } + script { + sendSlackNotifications("danger", "BUILD FAILURE", true, "#corda-corda4-open-source-build-notifications") + if (isReleaseTag || isReleaseBranch || isReleaseCandidate) { + sendEmailNotifications("${env.EMAIL_RECIPIENTS}") + } + } } cleanup { deleteDir() /* clean up our workspace */ From cd8ecac19e7d200843bcd48ed1407b6d4c77d0ab Mon Sep 17 00:00:00 2001 From: Connel McGovern <100574906+mcgovc@users.noreply.github.com> Date: Mon, 9 May 2022 13:17:58 +0100 Subject: [PATCH 25/37] INFRA-1743 Slack & E-mail notification --- .ci/dev/regression/Jenkinsfile | 56 ++++++++++++---------------------- 1 file changed, 19 insertions(+), 37 deletions(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index d24250c6b7..8cc8686a50 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -3,6 +3,8 @@ * Jenkins pipeline to build Corda OS release branches and tags. * PLEASE NOTE: we DO want to run a build for each commit!!! */ +@Library('corda-shared-build-pipeline-steps') + /** * Sense environment @@ -41,17 +43,6 @@ def nexusIqStageChoices = [nexusDefaultIqStage].plus( 'operate' ].minus([nexusDefaultIqStage])) -/** - * define an empty teamsWebHookURL and if it is a Release Branch - * then set it for the Corda 4 Jenkins Connector - */ -def teamsWebHookURL = "" -if (isReleaseBranch || isReleaseTag){ - withCredentials([string(credentialsId: 'ms-teams-webhook', variable: 'webhook_url')]) { - teamsWebHookURL = "$webhook_url" - } -} - /** * Common Gradle arguments for all Gradle executions */ @@ -74,18 +65,6 @@ pipeline { parallelsAlwaysFailFast() timeout(time: 6, unit: 'HOURS') timestamps() - office365ConnectorWebhooks([[ - name : "Corda 4 Jenkins Connector", - notifyBackToNormal : true, - startNotification : false, - notifyFailure : true, - notifySuccess : true, - notifyNotBuilt : false, - notifyAborted : false, - notifyRepeatedFailure: true, - notifyUnstable : true, - url : "${teamsWebHookURL}" - ]]) } parameters { @@ -102,6 +81,7 @@ pipeline { CORDA_ARTIFACTORY_PASSWORD = "${env.ARTIFACTORY_CREDENTIALS_PSW}" CORDA_ARTIFACTORY_USERNAME = "${env.ARTIFACTORY_CREDENTIALS_USR}" DOCKER_URL = "https://index.docker.io/v1/" + EMAIL_RECIPIENTS = credentials('corda4-email-recipient') } stages { @@ -383,21 +363,23 @@ pipeline { } } } + success { + script { + sendSlackNotifications("good", "BUILD PASSED", false, "#corda-corda4-open-source-build-notifications") + } + } + unstable { + script { + sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", false, "#corda-corda4-open-source-build-notifications") + } + } failure { - script { - def statusSymbol = '\u274c' - if (isReleaseTag || isReleaseBranch || isReleaseCandidate) { - emailext subject: "$statusSymbol " + '$PROJECT_NAME - Build # $BUILD_NUMBER - $BUILD_STATUS!', - body: '${SCRIPT, template="groovy-html.template"}', - recipientProviders: [ - [$class: 'CulpritsRecipientProvider'], - [$class: 'RequesterRecipientProvider'] - ], - mimeType: 'text/html', - replyTo: '$DEFAULT_REPLYTO', - to: "adel.el-beik@r3.com" - } - } + script { + sendSlackNotifications("danger", "BUILD FAILURE", true, "#corda-corda4-open-source-build-notifications") + if (isReleaseTag || isReleaseBranch || isReleaseCandidate) { + sendEmailNotifications("${env.EMAIL_RECIPIENTS}") + } + } } cleanup { deleteDir() /* clean up our workspace */ From e33265f60d8c214a1d373983541c2d72ef4772c8 Mon Sep 17 00:00:00 2001 From: Adel El-Beik Date: Mon, 9 May 2022 13:36:16 +0100 Subject: [PATCH 26/37] ENT-6765: Upgraded quassar and hibernate. --- build.gradle | 2 +- constants.properties | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index b212a77909..eaa2cbad34 100644 --- a/build.gradle +++ b/build.gradle @@ -98,7 +98,7 @@ buildscript { ext.hamkrest_version = '1.7.0.0' ext.jopt_simple_version = '5.0.2' ext.jansi_version = '1.18' - ext.hibernate_version = '5.4.3.Final' + ext.hibernate_version = '5.4.32.Final' ext.h2_version = '1.4.199' // Update docs if renamed or removed. ext.rxjava_version = '1.3.8' ext.dokka_version = '0.9.17' diff --git a/constants.properties b/constants.properties index ca2248617b..e7a496b5b8 100644 --- a/constants.properties +++ b/constants.properties @@ -14,8 +14,7 @@ java8MinUpdateVersion=171 platformVersion=7 guavaVersion=28.0-jre # Quasar version to use with Java 8: -quasarVersion=0.7.12_r3 -quasarClassifier=jdk8 +quasarVersion=0.7.15_r3 # Quasar version to use with Java 11: quasarVersion11=0.8.0_r3 jdkClassifier11=jdk11 From c30e7be3a721e3d20145c4c79a0df3ab99789ae7 Mon Sep 17 00:00:00 2001 From: Connel McGovern <100574906+mcgovc@users.noreply.github.com> Date: Mon, 9 May 2022 16:16:20 +0100 Subject: [PATCH 27/37] Update Jenkinsfile --- .ci/dev/regression/Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index e28197963d..1038f74a75 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -364,12 +364,12 @@ pipeline { } success { script { - sendSlackNotifications("good", "BUILD PASSED", false, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("good", "BUILD PASSED", true, "#corda-corda4-open-source-build-notifications") } } unstable { script { - sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", false, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", true, "#corda-corda4-open-source-build-notifications") } } failure { From 48980134c92b7ba17d5a44cd34cdf7c7cd39a4b2 Mon Sep 17 00:00:00 2001 From: Connel McGovern <100574906+mcgovc@users.noreply.github.com> Date: Mon, 9 May 2022 16:16:32 +0100 Subject: [PATCH 28/37] Update Jenkinsfile --- .ci/dev/regression/Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index e28197963d..1038f74a75 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -364,12 +364,12 @@ pipeline { } success { script { - sendSlackNotifications("good", "BUILD PASSED", false, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("good", "BUILD PASSED", true, "#corda-corda4-open-source-build-notifications") } } unstable { script { - sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", false, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", true, "#corda-corda4-open-source-build-notifications") } } failure { From 64849455133e3262a1aa905accf46ff6c90cdcf2 Mon Sep 17 00:00:00 2001 From: Connel McGovern <100574906+mcgovc@users.noreply.github.com> Date: Mon, 9 May 2022 16:16:44 +0100 Subject: [PATCH 29/37] Update Jenkinsfile --- .ci/dev/regression/Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 8cc8686a50..a84d758c47 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -365,12 +365,12 @@ pipeline { } success { script { - sendSlackNotifications("good", "BUILD PASSED", false, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("good", "BUILD PASSED", true, "#corda-corda4-open-source-build-notifications") } } unstable { script { - sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", false, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", true, "#corda-corda4-open-source-build-notifications") } } failure { From bdf96634ee244ea858a5cd362947549e8e5d8615 Mon Sep 17 00:00:00 2001 From: Connel McGovern <100574906+mcgovc@users.noreply.github.com> Date: Wed, 11 May 2022 14:24:25 +0100 Subject: [PATCH 30/37] NOTICK Remove Slack tagging on successful/unstable builds --- .ci/dev/regression/Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 1038f74a75..e28197963d 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -364,12 +364,12 @@ pipeline { } success { script { - sendSlackNotifications("good", "BUILD PASSED", true, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("good", "BUILD PASSED", false, "#corda-corda4-open-source-build-notifications") } } unstable { script { - sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", true, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", false, "#corda-corda4-open-source-build-notifications") } } failure { From ab19a61169ce1d8128e88d62e991ca25791791b2 Mon Sep 17 00:00:00 2001 From: Connel McGovern <100574906+mcgovc@users.noreply.github.com> Date: Wed, 11 May 2022 14:25:07 +0100 Subject: [PATCH 31/37] NOTICK Remove Slack tagging on successful/unstable builds --- .ci/dev/regression/Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 1038f74a75..e28197963d 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -364,12 +364,12 @@ pipeline { } success { script { - sendSlackNotifications("good", "BUILD PASSED", true, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("good", "BUILD PASSED", false, "#corda-corda4-open-source-build-notifications") } } unstable { script { - sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", true, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", false, "#corda-corda4-open-source-build-notifications") } } failure { From bbb6b1a51dbf7c9c8ed070302f0a38b15a8ddb85 Mon Sep 17 00:00:00 2001 From: Connel McGovern <100574906+mcgovc@users.noreply.github.com> Date: Wed, 11 May 2022 14:26:04 +0100 Subject: [PATCH 32/37] NOTICK Remove Slack tagging on successful/unstable builds --- .ci/dev/regression/Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index a84d758c47..8cc8686a50 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -365,12 +365,12 @@ pipeline { } success { script { - sendSlackNotifications("good", "BUILD PASSED", true, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("good", "BUILD PASSED", false, "#corda-corda4-open-source-build-notifications") } } unstable { script { - sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", true, "#corda-corda4-open-source-build-notifications") + sendSlackNotifications("warning", "BUILD UNSTABLE - Unstable Builds are likely a result of Nexus Sonar Scanner violations", false, "#corda-corda4-open-source-build-notifications") } } failure { From bfcd1d8791bef3b8335b2d7c4c3b280e1805e435 Mon Sep 17 00:00:00 2001 From: Tamas Veingartner Date: Mon, 8 Jun 2020 18:03:02 +0100 Subject: [PATCH 33/37] ENT-5379 Reconnecting RPC fixed to recognize shutdown calls and break reconnect attempts (#6316) --- .../CordaRPCClientReconnectionTest.kt | 23 +++++++++++++++++++ .../rpc/internal/ReconnectingCordaRPCOps.kt | 8 ++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/client/rpc/src/integration-test/kotlin/net/corda/client/rpcreconnect/CordaRPCClientReconnectionTest.kt b/client/rpc/src/integration-test/kotlin/net/corda/client/rpcreconnect/CordaRPCClientReconnectionTest.kt index 031b990b0a..70ae13731f 100644 --- a/client/rpc/src/integration-test/kotlin/net/corda/client/rpcreconnect/CordaRPCClientReconnectionTest.kt +++ b/client/rpc/src/integration-test/kotlin/net/corda/client/rpcreconnect/CordaRPCClientReconnectionTest.kt @@ -293,4 +293,27 @@ class CordaRPCClientReconnectionTest { .isInstanceOf(RPCException::class.java) } } + + @Test(timeout=300_000) + fun `rpc client does not attempt to reconnect after shutdown`() { + driver(DriverParameters(cordappsForAllNodes = emptyList())) { + val address = NetworkHostAndPort("localhost", portAllocator.nextPort()) + fun startNode(): NodeHandle { + return startNode( + providedName = CHARLIE_NAME, + rpcUsers = listOf(CordaRPCClientTest.rpcUser), + customOverrides = mapOf("rpcSettings.address" to address.toString()) + ).getOrThrow() + } + + val node = startNode() + val client = CordaRPCClient(node.rpcAddress, config) + (client.start(rpcUser.username, rpcUser.password, gracefulReconnect = gracefulReconnect)).use { + val rpcOps = it.proxy as ReconnectingCordaRPCOps + rpcOps.shutdown() + // If we get here we know we're not stuck in a reconnect cycle with a node that's been shut down + assertThat(rpcOps.reconnectingRPCConnection.isClosed()) + } + } + } } diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt index 9fdfa6089a..af3c7ab1b5 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt @@ -311,13 +311,18 @@ class ReconnectingCordaRPCOps private constructor( checkIfClosed() var remainingAttempts = maxNumberOfAttempts var lastException: Throwable? = null - while (remainingAttempts != 0) { + while (remainingAttempts != 0 && !reconnectingRPCConnection.isClosed()) { try { log.debug { "Invoking RPC $method..." } return method.invoke(reconnectingRPCConnection.proxy, *(args ?: emptyArray())).also { log.debug { "RPC $method invoked successfully." } } } catch (e: InvocationTargetException) { + if (method.name.equals("shutdown", true)) { + log.debug("Shutdown invoked, stop reconnecting.", e) + reconnectingRPCConnection.notifyServerAndClose() + break + } when (e.targetException) { is RejectedCommandException -> { log.warn("Node is being shutdown. Operation ${method.name} rejected. Retrying when node is up...", e) @@ -349,6 +354,7 @@ class ReconnectingCordaRPCOps private constructor( } } + if (reconnectingRPCConnection.isClosed()) return null throw MaxRpcRetryException(maxNumberOfAttempts, method, lastException) } From a5a0c64e2d7064aaf43ecbcb7eae5af1a55a3c53 Mon Sep 17 00:00:00 2001 From: Ryan Fowler Date: Mon, 27 Jul 2020 14:09:26 +0100 Subject: [PATCH 34/37] CORDA-3918: Port of ENT-5417: Allow exceptions to propagate when shutdown commands are called (#6516) --- .../rpc/internal/ReconnectingCordaRPCOps.kt | 19 ++++++++++--------- .../net/corda/tools/shell/InteractiveShell.kt | 10 ++++++---- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt index af3c7ab1b5..7db8597ba3 100644 --- a/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt +++ b/client/rpc/src/main/kotlin/net/corda/client/rpc/internal/ReconnectingCordaRPCOps.kt @@ -292,6 +292,7 @@ class ReconnectingCordaRPCOps private constructor( } private class ErrorInterceptingHandler(val reconnectingRPCConnection: ReconnectingRPCConnection) : InvocationHandler { private fun Method.isStartFlow() = name.startsWith("startFlow") || name.startsWith("startTrackedFlow") + private fun Method.isShutdown() = name == "shutdown" || name == "gracefulShutdown" || name == "terminate" private fun checkIfIsStartFlow(method: Method, e: InvocationTargetException) { if (method.isStartFlow()) { @@ -306,7 +307,7 @@ class ReconnectingCordaRPCOps private constructor( * * A negative number for [maxNumberOfAttempts] means an unlimited number of retries will be performed. */ - @Suppress("ThrowsCount", "ComplexMethod") + @Suppress("ThrowsCount", "ComplexMethod", "NestedBlockDepth") private fun doInvoke(method: Method, args: Array?, maxNumberOfAttempts: Int): Any? { checkIfClosed() var remainingAttempts = maxNumberOfAttempts @@ -318,20 +319,20 @@ class ReconnectingCordaRPCOps private constructor( log.debug { "RPC $method invoked successfully." } } } catch (e: InvocationTargetException) { - if (method.name.equals("shutdown", true)) { - log.debug("Shutdown invoked, stop reconnecting.", e) - reconnectingRPCConnection.notifyServerAndClose() - break - } when (e.targetException) { is RejectedCommandException -> { log.warn("Node is being shutdown. Operation ${method.name} rejected. Retrying when node is up...", e) reconnectingRPCConnection.reconnectOnError(e) } is ConnectionFailureException -> { - log.warn("Failed to perform operation ${method.name}. Connection dropped. Retrying....", e) - reconnectingRPCConnection.reconnectOnError(e) - checkIfIsStartFlow(method, e) + if (method.isShutdown()) { + log.debug("Shutdown invoked, stop reconnecting.", e) + reconnectingRPCConnection.notifyServerAndClose() + } else { + log.warn("Failed to perform operation ${method.name}. Connection dropped. Retrying....", e) + reconnectingRPCConnection.reconnectOnError(e) + checkIfIsStartFlow(method, e) + } } is RPCException -> { rethrowIfUnrecoverable(e.targetException as RPCException) diff --git a/tools/shell/src/main/kotlin/net/corda/tools/shell/InteractiveShell.kt b/tools/shell/src/main/kotlin/net/corda/tools/shell/InteractiveShell.kt index bc00b7b53a..d78f4be24f 100644 --- a/tools/shell/src/main/kotlin/net/corda/tools/shell/InteractiveShell.kt +++ b/tools/shell/src/main/kotlin/net/corda/tools/shell/InteractiveShell.kt @@ -111,6 +111,8 @@ object InteractiveShell { YAML } + private fun isShutdownCmd(cmd: String) = cmd == "shutdown" || cmd == "gracefulShutdown" || cmd == "terminate" + fun startShell(configuration: ShellConfiguration, classLoader: ClassLoader? = null, standalone: Boolean = false) { makeRPCConnection = { username: String, password: String -> val connection = if (standalone) { @@ -623,6 +625,10 @@ object InteractiveShell { throw e.rootCause } } + if (isShutdownCmd(cmd)) { + out.println("Called 'shutdown' on the node.\nQuitting the shell now.").also { out.flush() } + onExit.invoke() + } } catch (e: StringToMethodCallParser.UnparseableCallException) { out.println(e.message, Decoration.bold, Color.red) if (e !is StringToMethodCallParser.UnparseableCallException.NoSuchFile) { @@ -634,10 +640,6 @@ object InteractiveShell { InputStreamSerializer.invokeContext = null InputStreamDeserializer.closeAll() } - if (cmd == "shutdown") { - out.println("Called 'shutdown' on the node.\nQuitting the shell now.").also { out.flush() } - onExit.invoke() - } return result } From 589c714cba4b7d5f4336a1df4f17a1addc943559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Waldemar=20=C5=BBurowski?= <45210402+wzur-r3@users.noreply.github.com> Date: Tue, 24 May 2022 16:45:09 +0200 Subject: [PATCH 35/37] CORE-4784: Generate license and wiki reports (#7181) --- .ci/dev/regression/Jenkinsfile | 68 +++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index 8cc8686a50..e279bd9d0f 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -5,7 +5,6 @@ */ @Library('corda-shared-build-pipeline-steps') - /** * Sense environment */ @@ -122,6 +121,73 @@ pipeline { ) } } + stage('Generate Wiki Report') { + when { + expression { isReleaseTag && !isInternalRelease && !isReleaseCandidate && !isReleasePatch } + beforeAgent true + } + agent { + docker { + image 'nexusiq-sonatype-cli:latest' + reuseNode true + registryUrl 'https://engineering-docker.software.r3.com/' + registryCredentialsId 'artifactory-credentials' + } + } + options { + retry(3) + } + environment { + NEXUS_APP_ID="${nexusAppId}" + NEXUS_APP_STAGE="${params.nexusIqStage}" + NEXUSIQ_CREDENTIALS = credentials('jenkins-nexusiq-credentials') + } + steps { + sh ''' + rm -f wiki-report.md + env NEXUSIQ_USERNAME="${NEXUSIQ_CREDENTIALS_USR}" \ + NEXUSIQ_PASSWORD="${NEXUSIQ_CREDENTIALS_PSW}" \ + /opt/app/wrapper wiki-report \ + --app "${NEXUS_APP_ID}" \ + --stage "${NEXUS_APP_STAGE}" >wiki-report.md + '''.stripIndent() + archiveArtifacts 'wiki-report.md' + } + } + stage('Generate Licence Report') { + when { + expression { isReleaseTag && !isInternalRelease && !isReleaseCandidate && !isReleasePatch } + beforeAgent true + } + agent { + docker { + image 'nexusiq-licence-report:latest' + reuseNode true + registryUrl 'https://engineering-docker.software.r3.com/' + registryCredentialsId 'artifactory-credentials' + } + } + options { + retry(3) + } + environment { + NEXUS_APP_ID="${nexusAppId}" + NEXUS_APP_STAGE="${params.nexusIqStage}" + NEXUSIQ_CREDENTIALS = credentials('jenkins-nexusiq-credentials') + } + steps { + sh '''\ + rm -rf report + env NEXUSIQ_USERNAME="${NEXUSIQ_CREDENTIALS_USR}" \ + NEXUSIQ_PASSWORD="${NEXUSIQ_CREDENTIALS_PSW}" \ + /opt/app/wrapper --write --outdir report \ + --force \ + --app "${NEXUS_APP_ID}" \ + --stage "${NEXUS_APP_STAGE}" + '''.stripIndent() + archiveArtifacts 'report/*.md' + } + } stage('All Tests') { when { From cb2c54e2b7d5f3fe9f90119d694627a4a8c1a3bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Waldemar=20=C5=BBurowski?= <45210402+wzur-r3@users.noreply.github.com> Date: Wed, 25 May 2022 14:38:29 +0200 Subject: [PATCH 36/37] NOTICK: added missing backslash (#7185) --- .ci/dev/regression/Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/dev/regression/Jenkinsfile b/.ci/dev/regression/Jenkinsfile index e279bd9d0f..22f3c51185 100644 --- a/.ci/dev/regression/Jenkinsfile +++ b/.ci/dev/regression/Jenkinsfile @@ -143,7 +143,7 @@ pipeline { NEXUSIQ_CREDENTIALS = credentials('jenkins-nexusiq-credentials') } steps { - sh ''' + sh '''\ rm -f wiki-report.md env NEXUSIQ_USERNAME="${NEXUSIQ_CREDENTIALS_USR}" \ NEXUSIQ_PASSWORD="${NEXUSIQ_CREDENTIALS_PSW}" \ From 63008c12db1b97ad9d04b69d6f284ed02613fc61 Mon Sep 17 00:00:00 2001 From: Waldemar Zurowski Date: Thu, 26 May 2022 11:39:41 +0200 Subject: [PATCH 37/37] Removed obsolete MS Teams hooks from nightly builds --- .ci/dev/publish-branch/Jenkinsfile.nightly | 35 ---------------------- 1 file changed, 35 deletions(-) diff --git a/.ci/dev/publish-branch/Jenkinsfile.nightly b/.ci/dev/publish-branch/Jenkinsfile.nightly index 1ab8353624..b7b36f7eb8 100644 --- a/.ci/dev/publish-branch/Jenkinsfile.nightly +++ b/.ci/dev/publish-branch/Jenkinsfile.nightly @@ -32,29 +32,6 @@ def nexusIqStageChoices = [nexusDefaultIqStage].plus( 'release', 'operate' ].minus([nexusDefaultIqStage])) -/** - * define an empty teamsWebHookURL and if it is a Release Branch - * then set it for the Corda 4 Jenkins Connector - */ -boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) -def teamsWebHookURL = "" -if (isReleaseBranch){ - withCredentials([string(credentialsId: 'ms-teams-webhook', variable: 'webhook_url')]) { - teamsWebHookURL = "$webhook_url" - } -} - -/** - * define an empty teamsWebHookURL and if it is a Release Branch - * then set it for the Corda 4 Jenkins Connector - */ -boolean isReleaseBranch = (env.BRANCH_NAME =~ /^release\/os\/.*/) -def teamsWebHookURL = "" -if (isReleaseBranch){ - withCredentials([string(credentialsId: 'ms-teams-webhook', variable: 'webhook_url')]) { - teamsWebHookURL = "$webhook_url" - } -} pipeline { agent { label 'standard' } @@ -65,18 +42,6 @@ pipeline { overrideIndexTriggers(false) timeout(time: 3, unit: 'HOURS') buildDiscarder(logRotator(daysToKeepStr: '14', artifactDaysToKeepStr: '14')) - office365ConnectorWebhooks([[ - name : "Corda 4 Jenkins Connector", - notifyBackToNormal : true, - startNotification : false, - notifyFailure : true, - notifySuccess : true, - notifyNotBuilt : false, - notifyAborted : false, - notifyRepeatedFailure: true, - notifyUnstable : true, - url : "${teamsWebHookURL}" - ]]) } parameters {