mirror of
https://github.com/corda/corda.git
synced 2024-12-18 12:46:29 +00:00
ENT-11251: Upgrade to Kotlin language version 1.9 (#7660)
This commit is contained in:
parent
3d90c1d850
commit
63f8e220c8
@ -5,7 +5,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
import static org.gradle.api.JavaVersion.VERSION_17
|
||||
import static org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
|
||||
import static org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_8
|
||||
import static org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
|
||||
|
||||
buildscript {
|
||||
// For sharing constants between builds
|
||||
@ -284,8 +284,8 @@ allprojects {
|
||||
|
||||
tasks.withType(KotlinCompile).configureEach {
|
||||
compilerOptions {
|
||||
languageVersion = KOTLIN_1_8
|
||||
apiVersion = KOTLIN_1_8
|
||||
languageVersion = KOTLIN_1_9
|
||||
apiVersion = KOTLIN_1_9
|
||||
jvmTarget = JVM_17
|
||||
javaParameters = true // Useful for reflection.
|
||||
freeCompilerArgs = ['-Xjvm-default=all-compatibility']
|
||||
|
@ -5,6 +5,6 @@ owasp.failOnError=false
|
||||
owasp.failBuildOnCVSS=11.0
|
||||
compilation.allWarningsAsErrors=false
|
||||
test.parallel=false
|
||||
kotlin_version=1.9.0
|
||||
kotlin_version=1.9.20
|
||||
commons_lang3_version=3.12.0
|
||||
json_api_version=1.1.4
|
||||
|
@ -10,7 +10,11 @@ import net.corda.node.services.config.AuthDataSourceType
|
||||
import net.corda.node.services.config.PasswordEncryption
|
||||
import net.corda.node.services.config.SecurityConfiguration
|
||||
import net.corda.nodeapi.internal.config.User
|
||||
import org.apache.shiro.authc.*
|
||||
import org.apache.shiro.authc.AuthenticationException
|
||||
import org.apache.shiro.authc.AuthenticationInfo
|
||||
import org.apache.shiro.authc.AuthenticationToken
|
||||
import org.apache.shiro.authc.SimpleAuthenticationInfo
|
||||
import org.apache.shiro.authc.UsernamePasswordToken
|
||||
import org.apache.shiro.authc.credential.PasswordMatcher
|
||||
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher
|
||||
import org.apache.shiro.authz.AuthorizationInfo
|
||||
@ -34,13 +38,8 @@ private typealias AuthServiceConfig = SecurityConfiguration.AuthService
|
||||
class RPCSecurityManagerImpl(config: AuthServiceConfig, cacheFactory: NamedCacheFactory) : RPCSecurityManager {
|
||||
|
||||
override val id = config.id
|
||||
private val manager: DefaultSecurityManager
|
||||
private val manager: DefaultSecurityManager = buildImpl(config, cacheFactory)
|
||||
|
||||
init {
|
||||
manager = buildImpl(config, cacheFactory)
|
||||
}
|
||||
|
||||
@Throws(FailedLoginException::class)
|
||||
override fun authenticate(principal: String, password: Password): AuthorizingSubject {
|
||||
password.use {
|
||||
val authToken = UsernamePasswordToken(principal, it.value)
|
||||
@ -83,11 +82,12 @@ class RPCSecurityManagerImpl(config: AuthServiceConfig, cacheFactory: NamedCache
|
||||
}
|
||||
return DefaultSecurityManager(realm).also {
|
||||
// Setup optional cache layer if configured
|
||||
it.cacheManager = config.options?.cache?.let {
|
||||
it.cacheManager = config.options?.cache?.let { options ->
|
||||
CaffeineCacheManager(
|
||||
timeToLiveSeconds = it.expireAfterSecs,
|
||||
maxSize = it.maxEntries,
|
||||
cacheFactory = cacheFactory)
|
||||
timeToLiveSeconds = options.expireAfterSecs,
|
||||
maxSize = options.maxEntries,
|
||||
cacheFactory = cacheFactory
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -193,8 +193,7 @@ private typealias ShiroCache<K, V> = org.apache.shiro.cache.Cache<K, V>
|
||||
/*
|
||||
* Adapts a [com.github.benmanes.caffeine.cache.Cache] to a [org.apache.shiro.cache.Cache] implementation.
|
||||
*/
|
||||
private fun <K : Any, V> Cache<K, V>.toShiroCache() = object : ShiroCache<K, V> {
|
||||
|
||||
private fun <K : Any, V : Any> Cache<K, V>.toShiroCache() = object : ShiroCache<K, V> {
|
||||
private val impl = this@toShiroCache
|
||||
|
||||
override operator fun get(key: K) = impl.getIfPresent(key)
|
||||
@ -231,13 +230,13 @@ private class CaffeineCacheManager(val maxSize: Long,
|
||||
|
||||
private val instances = ConcurrentHashMap<String, ShiroCache<*, *>>()
|
||||
|
||||
override fun <K : Any, V> getCache(name: String): ShiroCache<K, V> {
|
||||
override fun <K : Any, V : Any> getCache(name: String): ShiroCache<K, V> {
|
||||
val result = instances[name] ?: buildCache<K, V>(name)
|
||||
instances.putIfAbsent(name, result)
|
||||
return uncheckedCast(result)
|
||||
}
|
||||
|
||||
private fun <K : Any, V> buildCache(name: String): ShiroCache<K, V> {
|
||||
private fun <K : Any, V : Any> buildCache(name: String): ShiroCache<K, V> {
|
||||
logger.info("Constructing cache '$name' with maximumSize=$maxSize, TTL=${timeToLiveSeconds}s")
|
||||
return cacheFactory.buildNamed<K, V>("RPCSecurityManagerShiroCache_$name").toShiroCache()
|
||||
}
|
||||
@ -245,4 +244,4 @@ private class CaffeineCacheManager(val maxSize: Long,
|
||||
companion object {
|
||||
private val logger = loggerFor<CaffeineCacheManager>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,17 +15,17 @@ class PersistentPartyInfoCache(private val networkMapCache: PersistentNetworkMap
|
||||
private val database: CordaPersistence) {
|
||||
|
||||
// probably better off using a BiMap here: https://www.baeldung.com/guava-bimap
|
||||
private val cordaX500NameToPartyIdCache = NonInvalidatingCache<CordaX500Name, SecureHash?>(
|
||||
cacheFactory = cacheFactory,
|
||||
name = "RecoveryPartyInfoCache_byCordaX500Name") { key ->
|
||||
database.transaction { queryByCordaX500Name(session, key) }
|
||||
}
|
||||
private val cordaX500NameToPartyIdCache = NonInvalidatingCache<CordaX500Name, SecureHash>(
|
||||
cacheFactory = cacheFactory,
|
||||
name = "RecoveryPartyInfoCache_byCordaX500Name"
|
||||
) { key -> database.transaction { queryByCordaX500Name(session, key) } }
|
||||
|
||||
private val partyIdToCordaX500NameCache = NonInvalidatingCache<SecureHash, CordaX500Name?>(
|
||||
cacheFactory = cacheFactory,
|
||||
name = "RecoveryPartyInfoCache_byPartyId") { key ->
|
||||
database.transaction { queryByPartyId(session, key) }
|
||||
}
|
||||
private val partyIdToCordaX500NameCache = NonInvalidatingCache<SecureHash, CordaX500Name>(
|
||||
cacheFactory = cacheFactory,
|
||||
name = "RecoveryPartyInfoCache_byPartyId"
|
||||
) { key ->
|
||||
database.transaction { queryByPartyId(session, key) }
|
||||
}
|
||||
|
||||
private lateinit var trackNetworkMapUpdates: Observable<NetworkMapCache.MapChange>
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package net.corda.node.utilities
|
||||
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache
|
||||
import com.github.benmanes.caffeine.cache.Weigher
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.internal.NamedCacheFactory
|
||||
import net.corda.core.utilities.contextLogger
|
||||
@ -10,7 +9,6 @@ import net.corda.nodeapi.internal.persistence.contextTransaction
|
||||
import net.corda.nodeapi.internal.persistence.currentDBSession
|
||||
import org.hibernate.Session
|
||||
import org.hibernate.internal.SessionImpl
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
@ -22,7 +20,8 @@ import java.util.stream.Stream
|
||||
*
|
||||
* This class relies heavily on the fact that compute operations in the cache are atomic for a particular key.
|
||||
*/
|
||||
abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
|
||||
@Suppress("TooManyFunctions")
|
||||
abstract class AppendOnlyPersistentMapBase<K : Any, V, E, out EK>(
|
||||
val toPersistentEntityKey: (K) -> EK,
|
||||
val fromPersistentEntity: (E) -> Pair<K, V>,
|
||||
val toPersistentEntity: (key: K, value: V) -> E,
|
||||
@ -326,9 +325,9 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
|
||||
}
|
||||
|
||||
// No one is writing, but we haven't looked in the database yet. This can only be when there are no writers.
|
||||
class Unknown<K, T>(private val map: AppendOnlyPersistentMapBase<K, T, *, *>,
|
||||
private val key: K,
|
||||
private val _valueLoader: () -> T?) : Transactional<T>() {
|
||||
class Unknown<K : Any, T>(private val map: AppendOnlyPersistentMapBase<K, T, *, *>,
|
||||
private val key: K,
|
||||
private val _valueLoader: () -> T?) : Transactional<T>() {
|
||||
override val value: T
|
||||
get() = valueWithoutIsolationDelegate.value ?: throw NoSuchElementException("Not present")
|
||||
override val isPresent: Boolean
|
||||
@ -351,11 +350,11 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
|
||||
|
||||
// Written in a transaction (uncommitted) somewhere, but there's a small window when this might be seen after commit,
|
||||
// hence the committed flag.
|
||||
class InFlight<K, T>(private val map: AppendOnlyPersistentMapBase<K, T, *, *>,
|
||||
private val key: K,
|
||||
val weight: Int,
|
||||
private val _readerValueLoader: () -> T?,
|
||||
private val _writerValueLoader: () -> T = { throw IllegalAccessException("No value loader provided") }) : Transactional<T>() {
|
||||
class InFlight<K : Any, T>(private val map: AppendOnlyPersistentMapBase<K, T, *, *>,
|
||||
private val key: K,
|
||||
val weight: Int,
|
||||
private val _readerValueLoader: () -> T?,
|
||||
private val _writerValueLoader: () -> T = { throw IllegalAccessException("No value loader provided") }) : Transactional<T>() {
|
||||
|
||||
// A flag to indicate this has now been committed, but hasn't yet been replaced with Committed. This also
|
||||
// de-duplicates writes of the Committed value to the cache.
|
||||
@ -363,10 +362,10 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
|
||||
|
||||
// What to do if a non-writer needs to see the value and it hasn't yet been committed to the database.
|
||||
// Can be updated into a no-op once evaluated.
|
||||
private val readerValueLoader = AtomicReference<() -> T?>(_readerValueLoader)
|
||||
private val readerValueLoader = AtomicReference(_readerValueLoader)
|
||||
// What to do if a writer needs to see the value and it hasn't yet been committed to the database.
|
||||
// Can be updated into a no-op once evaluated.
|
||||
private val writerValueLoader = AtomicReference<() -> T>(_writerValueLoader)
|
||||
private val writerValueLoader = AtomicReference(_writerValueLoader)
|
||||
|
||||
fun alsoWrite(_value: T) {
|
||||
// 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>(
|
||||
// and then stop saying the transaction is writing the key.
|
||||
tx.onCommit {
|
||||
strongMap.cache.asMap().computeIfPresent(strongKey) { _, transactional: Transactional<T> ->
|
||||
if (transactional is Transactional.InFlight<*, T>) {
|
||||
if (transactional is InFlight<*, T>) {
|
||||
transactional.committed.set(true)
|
||||
val value = transactional.peekableValue
|
||||
if (value != null) {
|
||||
Transactional.Committed(value)
|
||||
Committed(value)
|
||||
} else {
|
||||
transactional
|
||||
}
|
||||
@ -447,7 +446,7 @@ abstract class AppendOnlyPersistentMapBase<K, V, E, out EK>(
|
||||
}
|
||||
|
||||
// Open for tests to override
|
||||
open class AppendOnlyPersistentMap<K, V, E, out EK>(
|
||||
open class AppendOnlyPersistentMap<K : Any, V, E, out EK>(
|
||||
cacheFactory: NamedCacheFactory,
|
||||
name: String,
|
||||
toPersistentEntityKey: (K) -> EK,
|
||||
@ -466,7 +465,7 @@ open class AppendOnlyPersistentMap<K, V, E, out EK>(
|
||||
}
|
||||
|
||||
// Same as above, but with weighted values (e.g. memory footprint sensitive).
|
||||
class WeightBasedAppendOnlyPersistentMap<K, V, E, out EK>(
|
||||
class WeightBasedAppendOnlyPersistentMap<K : Any, V, E, out EK>(
|
||||
cacheFactory: NamedCacheFactory,
|
||||
name: String,
|
||||
toPersistentEntityKey: (K) -> EK,
|
||||
@ -485,7 +484,7 @@ class WeightBasedAppendOnlyPersistentMap<K, V, E, out EK>(
|
||||
override val cache = NonInvalidatingWeightBasedCache(
|
||||
cacheFactory = cacheFactory,
|
||||
name = name,
|
||||
weigher = Weigher { key, value: Transactional<V> ->
|
||||
weigher = { key, value: Transactional<V> ->
|
||||
value.shallowSize + if (value is Transactional.InFlight<*, *>) {
|
||||
value.weight * 2
|
||||
} else {
|
||||
|
@ -6,21 +6,17 @@ import com.github.benmanes.caffeine.cache.LoadingCache
|
||||
import com.github.benmanes.caffeine.cache.Weigher
|
||||
import net.corda.core.internal.NamedCacheFactory
|
||||
|
||||
class NonInvalidatingCache<K, V> private constructor(
|
||||
val cache: LoadingCache<K, V>
|
||||
) : LoadingCache<K, V> by cache {
|
||||
|
||||
constructor(cacheFactory: NamedCacheFactory, name: String, loadFunction: (K) -> V) :
|
||||
this(buildCache(cacheFactory, name, loadFunction))
|
||||
class NonInvalidatingCache<K : Any, V : Any> private constructor(val cache: LoadingCache<K, V>) : LoadingCache<K, V> by cache {
|
||||
constructor(cacheFactory: NamedCacheFactory, name: String, loadFunction: (K) -> V?) : this(buildCache(cacheFactory, name, loadFunction))
|
||||
|
||||
private companion object {
|
||||
private fun <K, V> buildCache(cacheFactory: NamedCacheFactory, name: String, loadFunction: (K) -> V): LoadingCache<K, V> {
|
||||
private fun <K : Any, V : Any> buildCache(cacheFactory: NamedCacheFactory, name: String, loadFunction: (K) -> V?): LoadingCache<K, V> {
|
||||
return cacheFactory.buildNamed(name, NonInvalidatingCacheLoader(loadFunction))
|
||||
}
|
||||
}
|
||||
|
||||
// TODO look into overriding loadAll() if we ever use it
|
||||
class NonInvalidatingCacheLoader<K, V>(val loadFunction: (K) -> V) : CacheLoader<K, V> {
|
||||
class NonInvalidatingCacheLoader<K : Any, V : Any>(val loadFunction: (K) -> V?) : CacheLoader<K, V> {
|
||||
override fun reload(key: K, oldValue: V): V {
|
||||
throw IllegalStateException("Non invalidating cache refreshed")
|
||||
}
|
||||
@ -29,16 +25,17 @@ class NonInvalidatingCache<K, V> private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
class NonInvalidatingWeightBasedCache<K, V> private constructor(
|
||||
val cache: LoadingCache<K, V>
|
||||
) : LoadingCache<K, V> by cache {
|
||||
constructor (cacheFactory: NamedCacheFactory, name: String, weigher: Weigher<K, V>, loadFunction: (K) -> V) :
|
||||
class NonInvalidatingWeightBasedCache<K : Any, V : Any> private constructor(val cache: LoadingCache<K, V>) : LoadingCache<K, V> by cache {
|
||||
constructor(cacheFactory: NamedCacheFactory, name: String, weigher: Weigher<K, V>, loadFunction: (K) -> V?) :
|
||||
this(buildCache(cacheFactory, name, weigher, loadFunction))
|
||||
|
||||
private companion object {
|
||||
private fun <K, V> buildCache(cacheFactory: NamedCacheFactory, name: String, weigher: Weigher<K, V>, loadFunction: (K) -> V): LoadingCache<K, V> {
|
||||
private fun <K : Any, V : Any> buildCache(cacheFactory: NamedCacheFactory,
|
||||
name: String,
|
||||
weigher: Weigher<K, V>,
|
||||
loadFunction: (K) -> V?): LoadingCache<K, V> {
|
||||
val builder = Caffeine.newBuilder().weigher(weigher)
|
||||
return cacheFactory.buildNamed(builder, name, NonInvalidatingCache.NonInvalidatingCacheLoader(loadFunction))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,17 +7,20 @@ import com.github.benmanes.caffeine.cache.LoadingCache
|
||||
import com.github.benmanes.caffeine.cache.RemovalListener
|
||||
import net.corda.core.internal.NamedCacheFactory
|
||||
|
||||
class NonInvalidatingUnboundCache<K, V> private constructor(
|
||||
val cache: LoadingCache<K, V>
|
||||
) : LoadingCache<K, V> by cache {
|
||||
|
||||
constructor(name: String, cacheFactory: NamedCacheFactory, loadFunction: (K) -> V, removalListener: RemovalListener<K, V> = RemovalListener { _, _, _ -> },
|
||||
class NonInvalidatingUnboundCache<K : Any, V : Any> private constructor(val cache: LoadingCache<K, V>) : LoadingCache<K, V> by cache {
|
||||
constructor(name: String,
|
||||
cacheFactory: NamedCacheFactory,
|
||||
loadFunction: (K) -> V?,
|
||||
removalListener: RemovalListener<K, V> = RemovalListener { _, _, _ -> },
|
||||
keysToPreload: () -> Iterable<K> = { emptyList() }) :
|
||||
this(buildCache(name, cacheFactory, loadFunction, removalListener, keysToPreload))
|
||||
|
||||
private companion object {
|
||||
private fun <K, V> buildCache(name: String, cacheFactory: NamedCacheFactory, loadFunction: (K) -> V, removalListener: RemovalListener<K, V>,
|
||||
keysToPreload: () -> Iterable<K>): LoadingCache<K, V> {
|
||||
private fun <K : Any, V : Any> buildCache(name: String,
|
||||
cacheFactory: NamedCacheFactory,
|
||||
loadFunction: (K) -> V?,
|
||||
removalListener: RemovalListener<K, V>,
|
||||
keysToPreload: () -> Iterable<K>): LoadingCache<K, V> {
|
||||
val builder = Caffeine.newBuilder().removalListener(removalListener).executor(SameThreadExecutor.getExecutor())
|
||||
return cacheFactory.buildNamed(builder, name, NonInvalidatingCacheLoader(loadFunction)).apply {
|
||||
getAll(keysToPreload())
|
||||
@ -26,11 +29,11 @@ class NonInvalidatingUnboundCache<K, V> private constructor(
|
||||
}
|
||||
|
||||
// TODO look into overriding loadAll() if we ever use it
|
||||
private class NonInvalidatingCacheLoader<K, V>(val loadFunction: (K) -> V) : CacheLoader<K, V> {
|
||||
private class NonInvalidatingCacheLoader<K : Any, V : Any>(val loadFunction: (K) -> V?) : CacheLoader<K, V> {
|
||||
override fun reload(key: K, oldValue: V): V {
|
||||
throw IllegalStateException("Non invalidating cache refreshed")
|
||||
}
|
||||
|
||||
override fun load(key: K) = loadFunction(key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import java.util.*
|
||||
/**
|
||||
* Implements an unbound caching layer on top of a table accessed via Hibernate mapping.
|
||||
*/
|
||||
class PersistentMap<K : Any, V, E, out EK>(
|
||||
class PersistentMap<K : Any, V : Any, E, out EK>(
|
||||
name: String,
|
||||
val toPersistentEntityKey: (K) -> EK,
|
||||
val fromPersistentEntity: (E) -> Pair<K, V>,
|
||||
@ -126,7 +126,7 @@ class PersistentMap<K : Any, V, E, out EK>(
|
||||
return result
|
||||
}
|
||||
|
||||
private class NotReallyMutableEntry<K, V>(key: K, value: V) : AbstractMap.SimpleImmutableEntry<K, V>(key, value), MutableMap.MutableEntry<K, V> {
|
||||
private class NotReallyMutableEntry<K, V>(key: K, value: V) : SimpleImmutableEntry<K, V>(key, value), MutableMap.MutableEntry<K, V> {
|
||||
override fun setValue(newValue: V): V {
|
||||
throw UnsupportedOperationException("Not really mutable. Implement if really required.")
|
||||
}
|
||||
|
@ -820,8 +820,9 @@ class FlowFrameworkTests {
|
||||
}
|
||||
|
||||
// When ported to ENT use the existing API there to properly retry the flow
|
||||
@Suppress("FunctionNaming") // For some reason this test produces invalid class names if the function name contains spaces
|
||||
@Test(timeout=300_000)
|
||||
fun `Hospitalized flow, resets to 'RUNNABLE' and clears exception when retried`() {
|
||||
fun Hospitalized_flow_resets_to_RUNNABLE_and_clears_exception_when_retried() {
|
||||
var firstRun = true
|
||||
var counter = 0
|
||||
val waitUntilHospitalizedTwice = Semaphore(-1)
|
||||
|
Loading…
Reference in New Issue
Block a user