Skip to content

Commit 63f8e22

Browse files
authored
ENT-11251: Upgrade to Kotlin language version 1.9 (corda#7660)
1 parent 3d90c1d commit 63f8e22

File tree

9 files changed

+73
-74
lines changed

9 files changed

+73
-74
lines changed

build.gradle

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
55

66
import static org.gradle.api.JavaVersion.VERSION_17
77
import static org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
8-
import static org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_8
8+
import static org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
99

1010
buildscript {
1111
// For sharing constants between builds
@@ -284,8 +284,8 @@ allprojects {
284284

285285
tasks.withType(KotlinCompile).configureEach {
286286
compilerOptions {
287-
languageVersion = KOTLIN_1_8
288-
apiVersion = KOTLIN_1_8
287+
languageVersion = KOTLIN_1_9
288+
apiVersion = KOTLIN_1_9
289289
jvmTarget = JVM_17
290290
javaParameters = true // Useful for reflection.
291291
freeCompilerArgs = ['-Xjvm-default=all-compatibility']

gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ owasp.failOnError=false
55
owasp.failBuildOnCVSS=11.0
66
compilation.allWarningsAsErrors=false
77
test.parallel=false
8-
kotlin_version=1.9.0
8+
kotlin_version=1.9.20
99
commons_lang3_version=3.12.0
1010
json_api_version=1.1.4

node/src/main/kotlin/net/corda/node/internal/security/RPCSecurityManagerImpl.kt

+15-16
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ import net.corda.node.services.config.AuthDataSourceType
1010
import net.corda.node.services.config.PasswordEncryption
1111
import net.corda.node.services.config.SecurityConfiguration
1212
import net.corda.nodeapi.internal.config.User
13-
import org.apache.shiro.authc.*
13+
import org.apache.shiro.authc.AuthenticationException
14+
import org.apache.shiro.authc.AuthenticationInfo
15+
import org.apache.shiro.authc.AuthenticationToken
16+
import org.apache.shiro.authc.SimpleAuthenticationInfo
17+
import org.apache.shiro.authc.UsernamePasswordToken
1418
import org.apache.shiro.authc.credential.PasswordMatcher
1519
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher
1620
import org.apache.shiro.authz.AuthorizationInfo
@@ -34,13 +38,8 @@ private typealias AuthServiceConfig = SecurityConfiguration.AuthService
3438
class RPCSecurityManagerImpl(config: AuthServiceConfig, cacheFactory: NamedCacheFactory) : RPCSecurityManager {
3539

3640
override val id = config.id
37-
private val manager: DefaultSecurityManager
41+
private val manager: DefaultSecurityManager = buildImpl(config, cacheFactory)
3842

39-
init {
40-
manager = buildImpl(config, cacheFactory)
41-
}
42-
43-
@Throws(FailedLoginException::class)
4443
override fun authenticate(principal: String, password: Password): AuthorizingSubject {
4544
password.use {
4645
val authToken = UsernamePasswordToken(principal, it.value)
@@ -83,11 +82,12 @@ class RPCSecurityManagerImpl(config: AuthServiceConfig, cacheFactory: NamedCache
8382
}
8483
return DefaultSecurityManager(realm).also {
8584
// Setup optional cache layer if configured
86-
it.cacheManager = config.options?.cache?.let {
85+
it.cacheManager = config.options?.cache?.let { options ->
8786
CaffeineCacheManager(
88-
timeToLiveSeconds = it.expireAfterSecs,
89-
maxSize = it.maxEntries,
90-
cacheFactory = cacheFactory)
87+
timeToLiveSeconds = options.expireAfterSecs,
88+
maxSize = options.maxEntries,
89+
cacheFactory = cacheFactory
90+
)
9191
}
9292
}
9393
}
@@ -193,8 +193,7 @@ private typealias ShiroCache<K, V> = org.apache.shiro.cache.Cache<K, V>
193193
/*
194194
* Adapts a [com.github.benmanes.caffeine.cache.Cache] to a [org.apache.shiro.cache.Cache] implementation.
195195
*/
196-
private fun <K : Any, V> Cache<K, V>.toShiroCache() = object : ShiroCache<K, V> {
197-
196+
private fun <K : Any, V : Any> Cache<K, V>.toShiroCache() = object : ShiroCache<K, V> {
198197
private val impl = this@toShiroCache
199198

200199
override operator fun get(key: K) = impl.getIfPresent(key)
@@ -231,18 +230,18 @@ private class CaffeineCacheManager(val maxSize: Long,
231230

232231
private val instances = ConcurrentHashMap<String, ShiroCache<*, *>>()
233232

234-
override fun <K : Any, V> getCache(name: String): ShiroCache<K, V> {
233+
override fun <K : Any, V : Any> getCache(name: String): ShiroCache<K, V> {
235234
val result = instances[name] ?: buildCache<K, V>(name)
236235
instances.putIfAbsent(name, result)
237236
return uncheckedCast(result)
238237
}
239238

240-
private fun <K : Any, V> buildCache(name: String): ShiroCache<K, V> {
239+
private fun <K : Any, V : Any> buildCache(name: String): ShiroCache<K, V> {
241240
logger.info("Constructing cache '$name' with maximumSize=$maxSize, TTL=${timeToLiveSeconds}s")
242241
return cacheFactory.buildNamed<K, V>("RPCSecurityManagerShiroCache_$name").toShiroCache()
243242
}
244243

245244
companion object {
246245
private val logger = loggerFor<CaffeineCacheManager>()
247246
}
248-
}
247+
}

node/src/main/kotlin/net/corda/node/services/network/PersistentPartyInfoCache.kt

+10-10
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,17 @@ class PersistentPartyInfoCache(private val networkMapCache: PersistentNetworkMap
1515
private val database: CordaPersistence) {
1616

1717
// probably better off using a BiMap here: https://www.baeldung.com/guava-bimap
18-
private val cordaX500NameToPartyIdCache = NonInvalidatingCache<CordaX500Name, SecureHash?>(
19-
cacheFactory = cacheFactory,
20-
name = "RecoveryPartyInfoCache_byCordaX500Name") { key ->
21-
database.transaction { queryByCordaX500Name(session, key) }
22-
}
18+
private val cordaX500NameToPartyIdCache = NonInvalidatingCache<CordaX500Name, SecureHash>(
19+
cacheFactory = cacheFactory,
20+
name = "RecoveryPartyInfoCache_byCordaX500Name"
21+
) { key -> database.transaction { queryByCordaX500Name(session, key) } }
2322

24-
private val partyIdToCordaX500NameCache = NonInvalidatingCache<SecureHash, CordaX500Name?>(
25-
cacheFactory = cacheFactory,
26-
name = "RecoveryPartyInfoCache_byPartyId") { key ->
27-
database.transaction { queryByPartyId(session, key) }
28-
}
23+
private val partyIdToCordaX500NameCache = NonInvalidatingCache<SecureHash, CordaX500Name>(
24+
cacheFactory = cacheFactory,
25+
name = "RecoveryPartyInfoCache_byPartyId"
26+
) { key ->
27+
database.transaction { queryByPartyId(session, key) }
28+
}
2929

3030
private lateinit var trackNetworkMapUpdates: Observable<NetworkMapCache.MapChange>
3131

node/src/main/kotlin/net/corda/node/utilities/AppendOnlyPersistentMap.kt

+17-18
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package net.corda.node.utilities
22

33
import com.github.benmanes.caffeine.cache.LoadingCache
4-
import com.github.benmanes.caffeine.cache.Weigher
54
import net.corda.core.crypto.SecureHash
65
import net.corda.core.internal.NamedCacheFactory
76
import net.corda.core.utilities.contextLogger
@@ -10,7 +9,6 @@ import net.corda.nodeapi.internal.persistence.contextTransaction
109
import net.corda.nodeapi.internal.persistence.currentDBSession
1110
import org.hibernate.Session
1211
import org.hibernate.internal.SessionImpl
13-
import java.util.*
1412
import java.util.concurrent.ConcurrentHashMap
1513
import java.util.concurrent.atomic.AtomicBoolean
1614
import java.util.concurrent.atomic.AtomicReference
@@ -22,7 +20,8 @@ import java.util.stream.Stream
2220
*
2321
* This class relies heavily on the fact that compute operations in the cache are atomic for a particular key.
2422
*/
25-
abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
23+
@Suppress("TooManyFunctions")
24+
abstract class AppendOnlyPersistentMapBase<K : Any, V, E, out EK>(
2625
val toPersistentEntityKey: (K) -> EK,
2726
val fromPersistentEntity: (E) -> Pair<K, V>,
2827
val toPersistentEntity: (key: K, value: V) -> E,
@@ -326,9 +325,9 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
326325
}
327326

328327
// No one is writing, but we haven't looked in the database yet. This can only be when there are no writers.
329-
class Unknown<K, T>(private val map: AppendOnlyPersistentMapBase<K, T, *, *>,
330-
private val key: K,
331-
private val _valueLoader: () -> T?) : Transactional<T>() {
328+
class Unknown<K : Any, T>(private val map: AppendOnlyPersistentMapBase<K, T, *, *>,
329+
private val key: K,
330+
private val _valueLoader: () -> T?) : Transactional<T>() {
332331
override val value: T
333332
get() = valueWithoutIsolationDelegate.value ?: throw NoSuchElementException("Not present")
334333
override val isPresent: Boolean
@@ -351,22 +350,22 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
351350

352351
// Written in a transaction (uncommitted) somewhere, but there's a small window when this might be seen after commit,
353352
// hence the committed flag.
354-
class InFlight<K, T>(private val map: AppendOnlyPersistentMapBase<K, T, *, *>,
355-
private val key: K,
356-
val weight: Int,
357-
private val _readerValueLoader: () -> T?,
358-
private val _writerValueLoader: () -> T = { throw IllegalAccessException("No value loader provided") }) : Transactional<T>() {
353+
class InFlight<K : Any, T>(private val map: AppendOnlyPersistentMapBase<K, T, *, *>,
354+
private val key: K,
355+
val weight: Int,
356+
private val _readerValueLoader: () -> T?,
357+
private val _writerValueLoader: () -> T = { throw IllegalAccessException("No value loader provided") }) : Transactional<T>() {
359358

360359
// A flag to indicate this has now been committed, but hasn't yet been replaced with Committed. This also
361360
// de-duplicates writes of the Committed value to the cache.
362361
private val committed = AtomicBoolean(false)
363362

364363
// What to do if a non-writer needs to see the value and it hasn't yet been committed to the database.
365364
// Can be updated into a no-op once evaluated.
366-
private val readerValueLoader = AtomicReference<() -> T?>(_readerValueLoader)
365+
private val readerValueLoader = AtomicReference(_readerValueLoader)
367366
// What to do if a writer needs to see the value and it hasn't yet been committed to the database.
368367
// Can be updated into a no-op once evaluated.
369-
private val writerValueLoader = AtomicReference<() -> T>(_writerValueLoader)
368+
private val writerValueLoader = AtomicReference(_writerValueLoader)
370369

371370
fun alsoWrite(_value: T) {
372371
// Make the lazy loader the writers see actually just return the value that has been set.
@@ -382,11 +381,11 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
382381
// and then stop saying the transaction is writing the key.
383382
tx.onCommit {
384383
strongMap.cache.asMap().computeIfPresent(strongKey) { _, transactional: Transactional<T> ->
385-
if (transactional is Transactional.InFlight<*, T>) {
384+
if (transactional is InFlight<*, T>) {
386385
transactional.committed.set(true)
387386
val value = transactional.peekableValue
388387
if (value != null) {
389-
Transactional.Committed(value)
388+
Committed(value)
390389
} else {
391390
transactional
392391
}
@@ -447,7 +446,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
447446
}
448447

449448
// Open for tests to override
450-
open class AppendOnlyPersistentMap<K, V, E, out EK>(
449+
open class AppendOnlyPersistentMap<K : Any, V, E, out EK>(
451450
cacheFactory: NamedCacheFactory,
452451
name: String,
453452
toPersistentEntityKey: (K) -> EK,
@@ -466,7 +465,7 @@ open class AppendOnlyPersistentMap<K, V, E, out EK>(
466465
}
467466

468467
// Same as above, but with weighted values (e.g. memory footprint sensitive).
469-
class WeightBasedAppendOnlyPersistentMap<K, V, E, out EK>(
468+
class WeightBasedAppendOnlyPersistentMap<K : Any, V, E, out EK>(
470469
cacheFactory: NamedCacheFactory,
471470
name: String,
472471
toPersistentEntityKey: (K) -> EK,
@@ -485,7 +484,7 @@ class WeightBasedAppendOnlyPersistentMap<K, V, E, out EK>(
485484
override val cache = NonInvalidatingWeightBasedCache(
486485
cacheFactory = cacheFactory,
487486
name = name,
488-
weigher = Weigher { key, value: Transactional<V> ->
487+
weigher = { key, value: Transactional<V> ->
489488
value.shallowSize + if (value is Transactional.InFlight<*, *>) {
490489
value.weight * 2
491490
} else {

node/src/main/kotlin/net/corda/node/utilities/NonInvalidatingCache.kt

+11-14
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,17 @@ import com.github.benmanes.caffeine.cache.LoadingCache
66
import com.github.benmanes.caffeine.cache.Weigher
77
import net.corda.core.internal.NamedCacheFactory
88

9-
class NonInvalidatingCache<K, V> private constructor(
10-
val cache: LoadingCache<K, V>
11-
) : LoadingCache<K, V> by cache {
12-
13-
constructor(cacheFactory: NamedCacheFactory, name: String, loadFunction: (K) -> V) :
14-
this(buildCache(cacheFactory, name, loadFunction))
9+
class NonInvalidatingCache<K : Any, V : Any> private constructor(val cache: LoadingCache<K, V>) : LoadingCache<K, V> by cache {
10+
constructor(cacheFactory: NamedCacheFactory, name: String, loadFunction: (K) -> V?) : this(buildCache(cacheFactory, name, loadFunction))
1511

1612
private companion object {
17-
private fun <K, V> buildCache(cacheFactory: NamedCacheFactory, name: String, loadFunction: (K) -> V): LoadingCache<K, V> {
13+
private fun <K : Any, V : Any> buildCache(cacheFactory: NamedCacheFactory, name: String, loadFunction: (K) -> V?): LoadingCache<K, V> {
1814
return cacheFactory.buildNamed(name, NonInvalidatingCacheLoader(loadFunction))
1915
}
2016
}
2117

2218
// TODO look into overriding loadAll() if we ever use it
23-
class NonInvalidatingCacheLoader<K, V>(val loadFunction: (K) -> V) : CacheLoader<K, V> {
19+
class NonInvalidatingCacheLoader<K : Any, V : Any>(val loadFunction: (K) -> V?) : CacheLoader<K, V> {
2420
override fun reload(key: K, oldValue: V): V {
2521
throw IllegalStateException("Non invalidating cache refreshed")
2622
}
@@ -29,16 +25,17 @@ class NonInvalidatingCache<K, V> private constructor(
2925
}
3026
}
3127

32-
class NonInvalidatingWeightBasedCache<K, V> private constructor(
33-
val cache: LoadingCache<K, V>
34-
) : LoadingCache<K, V> by cache {
35-
constructor (cacheFactory: NamedCacheFactory, name: String, weigher: Weigher<K, V>, loadFunction: (K) -> V) :
28+
class NonInvalidatingWeightBasedCache<K : Any, V : Any> private constructor(val cache: LoadingCache<K, V>) : LoadingCache<K, V> by cache {
29+
constructor(cacheFactory: NamedCacheFactory, name: String, weigher: Weigher<K, V>, loadFunction: (K) -> V?) :
3630
this(buildCache(cacheFactory, name, weigher, loadFunction))
3731

3832
private companion object {
39-
private fun <K, V> buildCache(cacheFactory: NamedCacheFactory, name: String, weigher: Weigher<K, V>, loadFunction: (K) -> V): LoadingCache<K, V> {
33+
private fun <K : Any, V : Any> buildCache(cacheFactory: NamedCacheFactory,
34+
name: String,
35+
weigher: Weigher<K, V>,
36+
loadFunction: (K) -> V?): LoadingCache<K, V> {
4037
val builder = Caffeine.newBuilder().weigher(weigher)
4138
return cacheFactory.buildNamed(builder, name, NonInvalidatingCache.NonInvalidatingCacheLoader(loadFunction))
4239
}
4340
}
44-
}
41+
}

node/src/main/kotlin/net/corda/node/utilities/NonInvalidatingUnboundCache.kt

+12-9
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,20 @@ import com.github.benmanes.caffeine.cache.LoadingCache
77
import com.github.benmanes.caffeine.cache.RemovalListener
88
import net.corda.core.internal.NamedCacheFactory
99

10-
class NonInvalidatingUnboundCache<K, V> private constructor(
11-
val cache: LoadingCache<K, V>
12-
) : LoadingCache<K, V> by cache {
13-
14-
constructor(name: String, cacheFactory: NamedCacheFactory, loadFunction: (K) -> V, removalListener: RemovalListener<K, V> = RemovalListener { _, _, _ -> },
10+
class NonInvalidatingUnboundCache<K : Any, V : Any> private constructor(val cache: LoadingCache<K, V>) : LoadingCache<K, V> by cache {
11+
constructor(name: String,
12+
cacheFactory: NamedCacheFactory,
13+
loadFunction: (K) -> V?,
14+
removalListener: RemovalListener<K, V> = RemovalListener { _, _, _ -> },
1515
keysToPreload: () -> Iterable<K> = { emptyList() }) :
1616
this(buildCache(name, cacheFactory, loadFunction, removalListener, keysToPreload))
1717

1818
private companion object {
19-
private fun <K, V> buildCache(name: String, cacheFactory: NamedCacheFactory, loadFunction: (K) -> V, removalListener: RemovalListener<K, V>,
20-
keysToPreload: () -> Iterable<K>): LoadingCache<K, V> {
19+
private fun <K : Any, V : Any> buildCache(name: String,
20+
cacheFactory: NamedCacheFactory,
21+
loadFunction: (K) -> V?,
22+
removalListener: RemovalListener<K, V>,
23+
keysToPreload: () -> Iterable<K>): LoadingCache<K, V> {
2124
val builder = Caffeine.newBuilder().removalListener(removalListener).executor(SameThreadExecutor.getExecutor())
2225
return cacheFactory.buildNamed(builder, name, NonInvalidatingCacheLoader(loadFunction)).apply {
2326
getAll(keysToPreload())
@@ -26,11 +29,11 @@ class NonInvalidatingUnboundCache<K, V> private constructor(
2629
}
2730

2831
// TODO look into overriding loadAll() if we ever use it
29-
private class NonInvalidatingCacheLoader<K, V>(val loadFunction: (K) -> V) : CacheLoader<K, V> {
32+
private class NonInvalidatingCacheLoader<K : Any, V : Any>(val loadFunction: (K) -> V?) : CacheLoader<K, V> {
3033
override fun reload(key: K, oldValue: V): V {
3134
throw IllegalStateException("Non invalidating cache refreshed")
3235
}
3336

3437
override fun load(key: K) = loadFunction(key)
3538
}
36-
}
39+
}

node/src/main/kotlin/net/corda/node/utilities/PersistentMap.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import java.util.*
1010
/**
1111
* Implements an unbound caching layer on top of a table accessed via Hibernate mapping.
1212
*/
13-
class PersistentMap<K : Any, V, E, out EK>(
13+
class PersistentMap<K : Any, V : Any, E, out EK>(
1414
name: String,
1515
val toPersistentEntityKey: (K) -> EK,
1616
val fromPersistentEntity: (E) -> Pair<K, V>,
@@ -126,7 +126,7 @@ class PersistentMap<K : Any, V, E, out EK>(
126126
return result
127127
}
128128

129-
private class NotReallyMutableEntry<K, V>(key: K, value: V) : AbstractMap.SimpleImmutableEntry<K, V>(key, value), MutableMap.MutableEntry<K, V> {
129+
private class NotReallyMutableEntry<K, V>(key: K, value: V) : SimpleImmutableEntry<K, V>(key, value), MutableMap.MutableEntry<K, V> {
130130
override fun setValue(newValue: V): V {
131131
throw UnsupportedOperationException("Not really mutable. Implement if really required.")
132132
}

node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -820,8 +820,9 @@ class FlowFrameworkTests {
820820
}
821821

822822
// When ported to ENT use the existing API there to properly retry the flow
823+
@Suppress("FunctionNaming") // For some reason this test produces invalid class names if the function name contains spaces
823824
@Test(timeout=300_000)
824-
fun `Hospitalized flow, resets to 'RUNNABLE' and clears exception when retried`() {
825+
fun Hospitalized_flow_resets_to_RUNNABLE_and_clears_exception_when_retried() {
825826
var firstRun = true
826827
var counter = 0
827828
val waitUntilHospitalizedTwice = Semaphore(-1)

0 commit comments

Comments
 (0)