mirror of
https://github.com/corda/corda.git
synced 2025-01-18 10:46:38 +00:00
Merge branch 'release/os/4.9' of https://github.com/corda/corda into release/os/4.9
This commit is contained in:
commit
75ada6fd3d
2
.ci/dev/regression/Jenkinsfile
vendored
2
.ci/dev/regression/Jenkinsfile
vendored
@ -319,7 +319,7 @@ pipeline {
|
||||
'./gradlew',
|
||||
COMMON_GRADLE_PARAMS,
|
||||
'docker:pushDockerImage',
|
||||
'-Pdocker.image.repository=corda/corda',
|
||||
'-Pdocker.image.repository=corda/community',
|
||||
'--image OFFICIAL'
|
||||
].join(' ')
|
||||
}
|
||||
|
@ -63,7 +63,8 @@ buildscript {
|
||||
ext.asm_version = '7.1'
|
||||
ext.artemis_version = '2.19.1'
|
||||
// TODO Upgrade Jackson only when corda is using kotlin 1.3.10
|
||||
ext.jackson_version = '2.9.7'
|
||||
ext.jackson_version = '2.11.1'
|
||||
ext.jackson_kotlin_version = '2.9.7'
|
||||
ext.jetty_version = '9.4.19.v20190610'
|
||||
ext.jersey_version = '2.25'
|
||||
ext.servlet_version = '4.0.1'
|
||||
@ -80,7 +81,7 @@ buildscript {
|
||||
ext.deterministic_rt_version = constants.getProperty('deterministicRtVersion')
|
||||
ext.okhttp_version = '3.14.2'
|
||||
ext.netty_version = '4.1.68.Final'
|
||||
ext.tcnative_version = '2.0.42.Final'
|
||||
ext.tcnative_version = constants.getProperty("tcnativeVersion")
|
||||
ext.typesafe_config_version = constants.getProperty("typesafeConfigVersion")
|
||||
ext.fileupload_version = '1.4'
|
||||
ext.kryo_version = '4.0.2'
|
||||
@ -101,7 +102,7 @@ buildscript {
|
||||
ext.hibernate_version = '5.4.3.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'
|
||||
ext.dokka_version = '0.10.1'
|
||||
ext.eddsa_version = '0.3.0'
|
||||
ext.dependency_checker_version = '5.2.0'
|
||||
ext.commons_collections_version = '4.3'
|
||||
@ -405,7 +406,6 @@ allprojects {
|
||||
includeGroup 'org.crashub'
|
||||
includeGroup 'com.github.bft-smart'
|
||||
includeGroup 'com.github.detro'
|
||||
includeGroup 'org.apache.activemq'
|
||||
}
|
||||
}
|
||||
maven {
|
||||
|
@ -9,7 +9,9 @@ dependencies {
|
||||
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||
// Jackson and its plugins: parsing to/from JSON and other textual formats.
|
||||
compile "com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version"
|
||||
compile("com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_kotlin_version") {
|
||||
exclude module: "jackson-databind"
|
||||
}
|
||||
// Yaml is useful for parsing strings to method calls.
|
||||
compile "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jackson_version"
|
||||
// This adds support for java.time types.
|
||||
|
@ -36,3 +36,4 @@ openSourceBranch=https://github.com/corda/corda/blob/release/os/4.4
|
||||
openSourceSamplesBranch=https://github.com/corda/samples/blob/release-V4
|
||||
jolokiaAgentVersion=1.6.1
|
||||
detektVersion=1.0.1
|
||||
tcnativeVersion=2.0.48.Final
|
||||
|
@ -16,5 +16,6 @@ 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
|
||||
const val CERTIFICATE_ROTATION = 9
|
||||
}
|
@ -2,6 +2,7 @@ FROM azul/zulu-openjdk:8u312
|
||||
|
||||
## Add packages, clean cache, create dirs, create corda user and change ownership
|
||||
RUN apt-get update && \
|
||||
apt-mark hold zulu8-jdk && \
|
||||
apt-get -y upgrade && \
|
||||
apt-get -y install bash curl unzip && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
|
@ -1,11 +1,10 @@
|
||||
FROM amazonlinux:2
|
||||
FROM amazoncorretto:8u312-al2
|
||||
|
||||
## Add packages, clean cache, create dirs, create corda user and change ownership
|
||||
RUN amazon-linux-extras enable corretto8 && \
|
||||
yum -y install java-1.8.0-amazon-corretto-devel && \
|
||||
yum -y install bash && \
|
||||
RUN yum -y install bash && \
|
||||
yum -y install curl && \
|
||||
yum -y install unzip && \
|
||||
yum -y install shadow-utils.x86_64 && \
|
||||
yum clean all && \
|
||||
rm -rf /var/cache/yum && \
|
||||
mkdir -p /opt/corda/cordapps && \
|
||||
|
@ -5,6 +5,10 @@ apply plugin: 'net.corda.plugins.publish-utils'
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'com.jfrog.artifactory'
|
||||
|
||||
dependencies {
|
||||
compile rootProject
|
||||
}
|
||||
|
||||
def internalPackagePrefixes(sourceDirs) {
|
||||
def prefixes = []
|
||||
// Kotlin allows packages to deviate from the directory structure, but let's assume they don't:
|
||||
@ -36,10 +40,13 @@ task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) {
|
||||
}
|
||||
|
||||
[dokka, dokkaJavadoc].collect {
|
||||
it.configure {
|
||||
it.configuration {
|
||||
moduleName = 'corda'
|
||||
processConfigurations = ['compile']
|
||||
sourceDirs = dokkaSourceDirs
|
||||
dokkaSourceDirs.collect { sourceDir ->
|
||||
sourceRoot {
|
||||
path = sourceDir.path
|
||||
}
|
||||
}
|
||||
includes = ['packages.md']
|
||||
jdkVersion = 8
|
||||
externalDocumentationLink {
|
||||
@ -52,7 +59,7 @@ task dokkaJavadoc(type: org.jetbrains.dokka.gradle.DokkaTask) {
|
||||
url = new URL("https://www.bouncycastle.org/docs/docs1.5on/")
|
||||
}
|
||||
internalPackagePrefixes.collect { packagePrefix ->
|
||||
packageOptions {
|
||||
perPackageOption {
|
||||
prefix = packagePrefix
|
||||
suppress = true
|
||||
}
|
||||
|
@ -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<Unit>() {
|
||||
class TestClearWarningsMethodIsBlocked : FlowLogic<Unit>() {
|
||||
@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()
|
||||
}
|
||||
|
@ -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<Unit>() {
|
||||
class TestGetMetamodelMethodIsBlocked : FlowLogic<Unit>() {
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
serviceHub.withEntityManager() {
|
||||
this.close()
|
||||
serviceHub.withEntityManager {
|
||||
this.metamodel
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -46,38 +47,61 @@ class RestrictedEntityManagerFlowTest {
|
||||
class TestJoinTransactionMethodIsBlocked : FlowLogic<Unit>() {
|
||||
@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()
|
||||
}
|
||||
|
@ -8,14 +8,13 @@ import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.MessagePac
|
||||
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPMessage
|
||||
import org.apache.activemq.artemis.protocol.amqp.broker.AmqpInterceptor
|
||||
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection
|
||||
import org.apache.qpid.proton.amqp.messaging.Data
|
||||
|
||||
class ArtemisMessageSizeChecksInterceptor(maxMessageSize: Int) : MessageSizeChecksInterceptor<Packet>(maxMessageSize), Interceptor {
|
||||
override fun getMessageSize(packet: Packet?): Int? {
|
||||
override fun getMessageSize(packet: Packet?): Long? {
|
||||
return when (packet) {
|
||||
// This is an estimate of how much memory a Message body takes up.
|
||||
// Note, it is only an estimate
|
||||
is MessagePacket -> (packet.message.persistentSize - packet.message.headersAndPropertiesEncodeSize - 4).toInt()
|
||||
is MessagePacket -> (packet.message.persistentSize - packet.message.headersAndPropertiesEncodeSize - 4)
|
||||
// Skip all artemis control messages.
|
||||
else -> null
|
||||
}
|
||||
@ -23,7 +22,7 @@ class ArtemisMessageSizeChecksInterceptor(maxMessageSize: Int) : MessageSizeChec
|
||||
}
|
||||
|
||||
class AmqpMessageSizeChecksInterceptor(maxMessageSize: Int) : MessageSizeChecksInterceptor<AMQPMessage>(maxMessageSize), AmqpInterceptor {
|
||||
override fun getMessageSize(packet: AMQPMessage?): Int? = (packet?.protonMessage?.body as? Data)?.value?.length
|
||||
override fun getMessageSize(packet: AMQPMessage?): Long? = packet?.wholeMessageSize
|
||||
}
|
||||
|
||||
/**
|
||||
@ -46,6 +45,6 @@ sealed class MessageSizeChecksInterceptor<T : Any>(private val maxMessageSize: I
|
||||
}
|
||||
|
||||
// get size of the message in byte, returns null if the message is null or size don't need to be checked.
|
||||
abstract fun getMessageSize(packet: T?): Int?
|
||||
abstract fun getMessageSize(packet: T?): Long?
|
||||
}
|
||||
|
||||
|
@ -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<String, Class<*>>?) {
|
||||
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 }
|
||||
}
|
||||
}
|
@ -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 <T> restrictDatabaseOperationFromJdbcSession(method: String, serviceHub: ServiceHub, operation: () -> T): T {
|
||||
return restrictDatabaseOperation("ServiceHub.jdbcSession.$method", serviceHub, operation)
|
||||
}
|
||||
|
||||
internal inline fun <T> restrictDatabaseOperationFromEntityManager(method: String, serviceHub: ServiceHub, operation: () -> T): T {
|
||||
return restrictDatabaseOperation("ServiceHub.withEntityManager.$method", serviceHub, operation)
|
||||
}
|
||||
|
||||
internal inline fun <T> 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()
|
||||
}
|
||||
}
|
@ -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 <T : Any?> unwrap(cls: Class<T>?): 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<String, Any>?) {
|
||||
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() }
|
||||
}
|
||||
}
|
@ -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<Cordapp>()
|
||||
private val cordappContext = CordappContext.create(cordapp, null, javaClass.classLoader, mock())
|
||||
private val serviceHub = mock<ServiceHub>().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<String, Class<*>> = 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<String, Class<*>> = 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<String, Class<*>> = 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
|
||||
}
|
||||
}
|
@ -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<EntityManager>()
|
||||
private val transaction = mock<EntityTransaction>()
|
||||
private val restrictedEntityManager = RestrictedEntityManager(entitymanager)
|
||||
private val cordapp = mock<Cordapp>()
|
||||
private val cordappContext = CordappContext.create(cordapp, null, javaClass.classLoader, mock())
|
||||
private val serviceHub = mock<ServiceHub>().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<String,Any> = 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<String, Any> = 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<String, Any> = 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<String, Any> = 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)
|
||||
}
|
||||
}
|
@ -291,9 +291,11 @@ class ProtonWrapperTests {
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `Send a message larger then maxMessageSize from AMQP to Artemis inbox`() {
|
||||
val maxMessageSize = 100_000
|
||||
val (server, artemisClient) = createArtemisServerAndClient(maxMessageSize)
|
||||
val amqpClient = createClient(maxMessageSize)
|
||||
val maxUserPayloadSize = 100_000
|
||||
val maxMessageSizeWithHeaders = maxUserPayloadSize + 512 // Adding a small "shim" to account for headers
|
||||
// and other non-payload bits of data
|
||||
val (server, artemisClient) = createArtemisServerAndClient(maxMessageSizeWithHeaders)
|
||||
val amqpClient = createClient(maxMessageSizeWithHeaders)
|
||||
val clientConnected = amqpClient.onConnection.toFuture()
|
||||
amqpClient.start()
|
||||
assertEquals(true, clientConnected.get().connected)
|
||||
@ -308,7 +310,7 @@ class ProtonWrapperTests {
|
||||
testProperty["TestProp"] = "1"
|
||||
|
||||
// Send normal message.
|
||||
val testData = ByteArray(maxMessageSize)
|
||||
val testData = ByteArray(maxUserPayloadSize)
|
||||
val message = amqpClient.createMessage(testData, sendAddress, CHARLIE_NAME.toString(), testProperty)
|
||||
amqpClient.write(message)
|
||||
assertEquals(MessageStatus.Acknowledged, message.onComplete.get())
|
||||
@ -317,7 +319,7 @@ class ProtonWrapperTests {
|
||||
assertArrayEquals(testData, ByteArray(received.bodySize).apply { received.bodyBuffer.readBytes(this) })
|
||||
|
||||
// Send message larger than max message size.
|
||||
val largeData = ByteArray(maxMessageSize + 1)
|
||||
val largeData = ByteArray(maxMessageSizeWithHeaders + 1)
|
||||
// Create message will fail.
|
||||
assertThatThrownBy {
|
||||
amqpClient.createMessage(largeData, sendAddress, CHARLIE_NAME.toString(), testProperty)
|
||||
|
@ -455,7 +455,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
||||
}
|
||||
}
|
||||
|
||||
fun clearNetworkMapCache() {
|
||||
open fun clearNetworkMapCache() {
|
||||
Node.printBasicNodeInfo("Clearing network map cache entries")
|
||||
log.info("Starting clearing of network map cache entries...")
|
||||
startDatabase()
|
||||
@ -690,9 +690,13 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
||||
val isShellStarted = InteractiveShell.startShellIfInstalled(configuration, cordappLoader)
|
||||
configuration.sshd?.port?.let {
|
||||
if (isShellStarted) {
|
||||
log.info("Binding Shell SSHD server on port $it.")
|
||||
Node.printBasicNodeInfo("SSH server listening on port", configuration.sshd!!.port.toString())
|
||||
log.info("SSH server listening on port: $it.")
|
||||
} else {
|
||||
log.info("SSH port defined but corda-shell is not installed in node's drivers directory")
|
||||
Node.printBasicNodeInfo(
|
||||
"SSH server not started. SSH port is defined but the corda-shell is not installed in node's drivers directory"
|
||||
)
|
||||
log.info("SSH server not started. SSH port is defined but the corda-shell is not installed in node's drivers directory")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1157,7 +1161,7 @@ abstract class AbstractNode<S>(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 <T : Any?> withEntityManager(block: EntityManager.() -> T): T {
|
||||
@ -1167,7 +1171,7 @@ abstract class AbstractNode<S>(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 {
|
||||
|
@ -564,6 +564,11 @@ open class Node(configuration: NodeConfiguration,
|
||||
return super.generateAndSaveNodeInfo()
|
||||
}
|
||||
|
||||
override fun clearNetworkMapCache() {
|
||||
initialiseSerialization()
|
||||
super.clearNetworkMapCache()
|
||||
}
|
||||
|
||||
override fun runDatabaseMigrationScripts(
|
||||
updateCoreSchemas: Boolean,
|
||||
updateAppSchemas: Boolean,
|
||||
|
@ -48,7 +48,6 @@ import net.corda.node.internal.subcommands.ValidateConfigurationCli.Companion.lo
|
||||
import net.corda.node.internal.subcommands.ValidateConfigurationCli.Companion.logRawConfig
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.config.shouldStartLocalShell
|
||||
import net.corda.node.services.config.shouldStartSSHDaemon
|
||||
import net.corda.node.utilities.registration.NodeRegistrationException
|
||||
import net.corda.nodeapi.internal.JVMAgentUtilities
|
||||
import net.corda.nodeapi.internal.addShutdownHook
|
||||
@ -263,19 +262,8 @@ open class NodeStartup : NodeStartupLogging {
|
||||
Node.printBasicNodeInfo("Node for \"$name\" started up and registered in $elapsed sec")
|
||||
|
||||
// Don't start the shell if there's no console attached.
|
||||
val isShellStarted = if (node.configuration.shouldStartLocalShell()) {
|
||||
if (node.configuration.shouldStartLocalShell()) {
|
||||
InteractiveShell.runLocalShellIfInstalled(node::stop)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
if (node.configuration.shouldStartSSHDaemon()) {
|
||||
if (isShellStarted) {
|
||||
Node.printBasicNodeInfo("SSH server listening on port", node.configuration.sshd!!.port.toString())
|
||||
} else {
|
||||
Node.printBasicNodeInfo(
|
||||
"SSH server not started. SSH port is defined but the corda-shell is not installed in node's drivers directory"
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
{ th ->
|
||||
|
@ -455,7 +455,10 @@ open class PersistentNetworkMapCache(cacheFactory: NamedCacheFactory,
|
||||
database.transaction {
|
||||
val result = getAllNodeInfos(session)
|
||||
logger.debug { "Number of node infos to be cleared: ${result.size}" }
|
||||
for (nodeInfo in result) session.remove(nodeInfo)
|
||||
for (nodeInfo in result) {
|
||||
session.remove(nodeInfo)
|
||||
archiveNamedIdentity(session, nodeInfo.toNodeInfo())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,6 +88,9 @@ class NodeAttachmentService @JvmOverloads constructor(
|
||||
|
||||
while (true) {
|
||||
val cursor = jar.nextJarEntry ?: break
|
||||
// Security check to stop directory traversal from filename entry
|
||||
require(!(cursor.name.contains("../"))) { "Bad character in ${cursor.name}" }
|
||||
require(!(cursor.name.contains("..\\"))) { "Bad character in ${cursor.name}" }
|
||||
if (manifestHasEntries && !allManifestEntries!!.remove(cursor.name)) extraFilesNotFoundInEntries.add(cursor)
|
||||
val entryPath = Paths.get(cursor.name)
|
||||
// Security check to stop zips trying to escape their rightful place.
|
||||
|
@ -271,7 +271,7 @@ class NodeVaultService(
|
||||
// This will cause a failure as we can't deserialize such states in the context of the `appClassloader`.
|
||||
// For now we ignore these states.
|
||||
// In the future we will use the AttachmentsClassloader to correctly deserialize and asses the relevancy.
|
||||
log.debug { "Could not deserialize state $idx from transaction $txId. Cause: $e" }
|
||||
log.warn("Could not deserialize state $idx from transaction $txId. Cause: $e")
|
||||
null
|
||||
}
|
||||
}.toMap()
|
||||
|
@ -46,14 +46,19 @@ import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.InputStream
|
||||
import java.net.URL
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.FileAlreadyExistsException
|
||||
import java.nio.file.FileSystem
|
||||
import java.nio.file.Path
|
||||
import java.util.*
|
||||
import java.util.jar.JarEntry
|
||||
import java.util.jar.JarInputStream
|
||||
import java.util.jar.JarOutputStream
|
||||
import java.util.jar.Manifest
|
||||
import kotlin.streams.toList
|
||||
import kotlin.test.*
|
||||
|
||||
@ -788,6 +793,32 @@ class NodeAttachmentServiceTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `attachments containing jar entries whose names expose malicious directory traversal are prevented`() {
|
||||
|
||||
fun createJarWithJarEntryTraversalAttack(jarEntryName: String): InputStream {
|
||||
val byteArrayOutputStream = ByteArrayOutputStream()
|
||||
JarOutputStream(byteArrayOutputStream, Manifest()).apply {
|
||||
putNextEntry(JarEntry(jarEntryName))
|
||||
write("some-text".toByteArray())
|
||||
closeEntry()
|
||||
close()
|
||||
}
|
||||
return ByteArrayInputStream(byteArrayOutputStream.toByteArray())
|
||||
}
|
||||
|
||||
val traversalAttackJarWin = createJarWithJarEntryTraversalAttack("..\\attack")
|
||||
val traversalAttackJarUnix = createJarWithJarEntryTraversalAttack("../attack")
|
||||
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
NodeAttachmentService.checkIsAValidJAR(traversalAttackJarWin)
|
||||
}
|
||||
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
NodeAttachmentService.checkIsAValidJAR(traversalAttackJarUnix)
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `attachments can be queried by providing a intersection of signers using an EQUAL statement - EQUAL containing a single public key`() {
|
||||
SelfCleaningDir().use { file ->
|
||||
|
@ -16,7 +16,7 @@ dependencies {
|
||||
cordaCompile project(':core')
|
||||
|
||||
|
||||
compile("com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version")
|
||||
compile("com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_kotlin_version")
|
||||
|
||||
// only included to control the `DemoClock` as part of the demo application
|
||||
// normally `:node` should not be depended on in any CorDapps
|
||||
|
@ -70,7 +70,7 @@ dependencies {
|
||||
}
|
||||
compile('org.springframework.boot:spring-boot-starter-log4j2')
|
||||
runtimeOnly("org.apache.logging.log4j:log4j-web:$log4j_version")
|
||||
compile("com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version")
|
||||
compile("com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_kotlin_version")
|
||||
compile project(":client:rpc")
|
||||
compile project(":client:jackson")
|
||||
compile project(":finance:workflows")
|
||||
|
@ -6,7 +6,7 @@ dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||
compile "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jackson_version"
|
||||
compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
|
||||
compile "com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version"
|
||||
compile "com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_kotlin_version"
|
||||
|
||||
compile "org.junit.jupiter:junit-jupiter-api:${junit_jupiter_version}"
|
||||
compile "junit:junit:${junit_version}"
|
||||
|
@ -52,7 +52,7 @@ dependencies {
|
||||
compile "com.typesafe:config:$typesafe_config_version"
|
||||
compile "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jackson_version"
|
||||
compile "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
|
||||
compile "com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version"
|
||||
compile "com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_kotlin_version"
|
||||
compile "info.picocli:picocli:$picocli_version"
|
||||
|
||||
// TornadoFX: A lightweight Kotlin framework for working with JavaFX UI's.
|
||||
|
Loading…
Reference in New Issue
Block a user