diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 584e5978..70c65a33 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -13,6 +13,8 @@ dependencies { implementation(libs.kotlinx.kover.gradle.plugin) implementation(libs.android.gradle.plugin) implementation(libs.maven.publish.gradle.plugin) + implementation(libs.ksp.gradle.plugin) + implementation(libs.sweetspi.gradle.plugin) implementation(libs.apache.commons.compress) implementation("testtool:plugin") } diff --git a/build-logic/src/main/kotlin/ckbuild.multiplatform-sweetspi.gradle.kts b/build-logic/src/main/kotlin/ckbuild.multiplatform-sweetspi.gradle.kts new file mode 100644 index 00000000..09588b65 --- /dev/null +++ b/build-logic/src/main/kotlin/ckbuild.multiplatform-sweetspi.gradle.kts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023-2024 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license. + */ + +import dev.whyoleg.sweetspi.gradle.* + +plugins { + kotlin("multiplatform") + id("com.google.devtools.ksp") + id("dev.whyoleg.sweetspi") +} + +kotlin { + withSweetSpi() +} diff --git a/cryptography-core/api/cryptography-core.api b/cryptography-core/api/cryptography-core.api index 327b419d..fc021b35 100644 --- a/cryptography-core/api/cryptography-core.api +++ b/cryptography-core/api/cryptography-core.api @@ -57,20 +57,9 @@ public final class dev/whyoleg/cryptography/CryptographyProvider$Companion { public final fun getDefault ()Ldev/whyoleg/cryptography/CryptographyProvider; } -public final class dev/whyoleg/cryptography/CryptographyProvider$Registry { - public static final field INSTANCE Ldev/whyoleg/cryptography/CryptographyProvider$Registry; - public final fun getRegisteredProviders ()Lkotlin/sequences/Sequence; - public final fun registerProvider (Ldev/whyoleg/cryptography/CryptographyProvider;)V - public final fun registerProvider (Lkotlin/Lazy;)V -} - public abstract interface annotation class dev/whyoleg/cryptography/CryptographyProviderApi : java/lang/annotation/Annotation { } -public abstract interface class dev/whyoleg/cryptography/CryptographyProviderContainer { - public abstract fun getProvider ()Lkotlin/Lazy; -} - public abstract interface annotation class dev/whyoleg/cryptography/DelicateCryptographyApi : java/lang/annotation/Annotation { } diff --git a/cryptography-core/api/cryptography-core.klib.api b/cryptography-core/api/cryptography-core.klib.api index 4d43f5b9..09c035a0 100644 --- a/cryptography-core/api/cryptography-core.klib.api +++ b/cryptography-core/api/cryptography-core.klib.api @@ -735,14 +735,6 @@ abstract class dev.whyoleg.cryptography/CryptographyProvider { // dev.whyoleg.cr final val Default // dev.whyoleg.cryptography/CryptographyProvider.Companion.Default|{}Default[0] final fun (): dev.whyoleg.cryptography/CryptographyProvider // dev.whyoleg.cryptography/CryptographyProvider.Companion.Default.|(){}[0] } - - final object Registry { // dev.whyoleg.cryptography/CryptographyProvider.Registry|null[0] - final val registeredProviders // dev.whyoleg.cryptography/CryptographyProvider.Registry.registeredProviders|{}registeredProviders[0] - final fun (): kotlin.sequences/Sequence // dev.whyoleg.cryptography/CryptographyProvider.Registry.registeredProviders.|(){}[0] - - final fun registerProvider(dev.whyoleg.cryptography/CryptographyProvider) // dev.whyoleg.cryptography/CryptographyProvider.Registry.registerProvider|registerProvider(dev.whyoleg.cryptography.CryptographyProvider){}[0] - final fun registerProvider(kotlin/Lazy) // dev.whyoleg.cryptography/CryptographyProvider.Registry.registerProvider|registerProvider(kotlin.Lazy){}[0] - } } final class dev.whyoleg.cryptography/CryptographyAlgorithmNotFoundException : dev.whyoleg.cryptography/CryptographyException { // dev.whyoleg.cryptography/CryptographyAlgorithmNotFoundException|null[0] @@ -820,3 +812,7 @@ final object dev.whyoleg.cryptography.algorithms/SHA3_384 : dev.whyoleg.cryptogr final object dev.whyoleg.cryptography.algorithms/SHA3_512 : dev.whyoleg.cryptography/CryptographyAlgorithmId // dev.whyoleg.cryptography.algorithms/SHA3_512|null[0] final object dev.whyoleg.cryptography.algorithms/SHA512 : dev.whyoleg.cryptography/CryptographyAlgorithmId // dev.whyoleg.cryptography.algorithms/SHA512|null[0] + +// Targets: [js] +final val dev.whyoleg.cryptography/init_dev_whyoleg_cryptography // dev.whyoleg.cryptography/init_dev_whyoleg_cryptography|{}init_dev_whyoleg_cryptography[0] + final fun (): dynamic // dev.whyoleg.cryptography/init_dev_whyoleg_cryptography.|(){}[0] diff --git a/cryptography-core/build.gradle.kts b/cryptography-core/build.gradle.kts index 57861da2..9581c41d 100644 --- a/cryptography-core/build.gradle.kts +++ b/cryptography-core/build.gradle.kts @@ -3,10 +3,10 @@ */ import ckbuild.* -import org.jetbrains.kotlin.gradle.* plugins { id("ckbuild.multiplatform-library") + id("ckbuild.multiplatform-sweetspi") } description = "cryptography-kotlin core API" @@ -17,18 +17,6 @@ kotlin { nativeTargets() wasmTargets() - @OptIn(ExperimentalKotlinGradlePluginApi::class) - applyDefaultHierarchyTemplate { - common { - group("nonJvm") { - withJs() - withWasmJs() - withWasmWasi() - group("native") - } - } - } - sourceSets.commonMain.dependencies { api(projects.cryptographyBigint) api(projects.cryptographyRandom) diff --git a/cryptography-core/src/commonMain/kotlin/CryptographyProvider.kt b/cryptography-core/src/commonMain/kotlin/CryptographyProvider.kt index 377445b2..a3fb832c 100644 --- a/cryptography-core/src/commonMain/kotlin/CryptographyProvider.kt +++ b/cryptography-core/src/commonMain/kotlin/CryptographyProvider.kt @@ -4,6 +4,9 @@ package dev.whyoleg.cryptography +import dev.whyoleg.sweetspi.* + +@Service @SubclassOptInRequired(CryptographyProviderApi::class) public abstract class CryptographyProvider { public abstract val name: String @@ -12,30 +15,11 @@ public abstract class CryptographyProvider { public open fun get(identifier: CryptographyAlgorithmId): A = getOrNull(identifier) ?: throw IllegalStateException("Algorithm not found: $identifier") - @CryptographyProviderApi - public object Registry { - private val providers = initProviders().toMutableList() - public val registeredProviders: Sequence - get() = providers.toList().asSequence().map(Lazy::value) - - public fun registerProvider(provider: CryptographyProvider) { - providers.add(lazyOf(provider)) - } - - public fun registerProvider(provider: Lazy) { - providers.add(provider) - } - } - public companion object { public val Default: CryptographyProvider by lazy { - @OptIn(CryptographyProviderApi::class) - checkNotNull(Registry.registeredProviders.firstOrNull()) { + checkNotNull(ServiceLoader.load().firstOrNull()) { "No providers registered. Please provide a dependency or register provider explicitly" } } } } - -// used only on JVM for ServiceLoader -internal expect fun initProviders(): List> diff --git a/cryptography-core/src/jvmMain/kotlin/CryptographyProvider.jvm.kt b/cryptography-core/src/jvmMain/kotlin/CryptographyProvider.jvm.kt deleted file mode 100644 index 391a55a3..00000000 --- a/cryptography-core/src/jvmMain/kotlin/CryptographyProvider.jvm.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2023-2024 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.whyoleg.cryptography - -import java.util.* - -@CryptographyProviderApi -public interface CryptographyProviderContainer { - public val provider: Lazy -} - -@OptIn(CryptographyProviderApi::class) -internal actual fun initProviders(): List> = Iterable { - ServiceLoader.load( - CryptographyProviderContainer::class.java, - CryptographyProviderContainer::class.java.classLoader - ).iterator() -}.map { it.provider } diff --git a/cryptography-core/src/nonJvmMain/kotlin/CryptographyProvider.nonJvm.kt b/cryptography-core/src/nonJvmMain/kotlin/CryptographyProvider.nonJvm.kt deleted file mode 100644 index ddce771d..00000000 --- a/cryptography-core/src/nonJvmMain/kotlin/CryptographyProvider.nonJvm.kt +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2023-2024 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license. - */ - -package dev.whyoleg.cryptography - -internal actual fun initProviders(): List> = emptyList() diff --git a/cryptography-providers/apple/build.gradle.kts b/cryptography-providers/apple/build.gradle.kts index 86b5486a..7f6c4b75 100644 --- a/cryptography-providers/apple/build.gradle.kts +++ b/cryptography-providers/apple/build.gradle.kts @@ -7,6 +7,7 @@ import org.jetbrains.kotlin.gradle.* plugins { id("ckbuild.multiplatform-library") + id("ckbuild.multiplatform-sweetspi") id("ckbuild.multiplatform-provider-tests") } diff --git a/cryptography-providers/apple/src/commonMain/kotlin/AppleCryptographyProvider.kt b/cryptography-providers/apple/src/commonMain/kotlin/AppleCryptographyProvider.kt index 96dc6320..cd6c31c7 100644 --- a/cryptography-providers/apple/src/commonMain/kotlin/AppleCryptographyProvider.kt +++ b/cryptography-providers/apple/src/commonMain/kotlin/AppleCryptographyProvider.kt @@ -7,10 +7,12 @@ package dev.whyoleg.cryptography.providers.apple import dev.whyoleg.cryptography.* import dev.whyoleg.cryptography.algorithms.* import dev.whyoleg.cryptography.providers.apple.algorithms.* +import dev.whyoleg.sweetspi.* -private val defaultProvider = lazy { AppleCryptographyProvider } +@ServiceProvider +internal val defaultProvider by lazy { AppleCryptographyProvider } -public val CryptographyProvider.Companion.Apple: CryptographyProvider by defaultProvider +public val CryptographyProvider.Companion.Apple: CryptographyProvider get() = defaultProvider internal object AppleCryptographyProvider : CryptographyProvider() { override val name: String get() = "Apple" @@ -37,8 +39,3 @@ internal object AppleCryptographyProvider : CryptographyProvider() { else -> null } as A? } - -@Suppress("DEPRECATION") -@OptIn(ExperimentalStdlibApi::class) -@EagerInitialization -private val initHook = CryptographyProvider.Registry.registerProvider(defaultProvider) diff --git a/cryptography-providers/jdk/build.gradle.kts b/cryptography-providers/jdk/build.gradle.kts index b55b8823..bf2175b9 100644 --- a/cryptography-providers/jdk/build.gradle.kts +++ b/cryptography-providers/jdk/build.gradle.kts @@ -7,6 +7,7 @@ import org.jetbrains.kotlin.gradle.* plugins { id("ckbuild.multiplatform-library") + id("ckbuild.multiplatform-sweetspi") id("ckbuild.multiplatform-provider-tests") } diff --git a/cryptography-providers/jdk/src/jvmMain/kotlin/JdkCryptographyProvider.kt b/cryptography-providers/jdk/src/jvmMain/kotlin/JdkCryptographyProvider.kt index 470150d1..6e6b01b9 100644 --- a/cryptography-providers/jdk/src/jvmMain/kotlin/JdkCryptographyProvider.kt +++ b/cryptography-providers/jdk/src/jvmMain/kotlin/JdkCryptographyProvider.kt @@ -8,12 +8,14 @@ import dev.whyoleg.cryptography.* import dev.whyoleg.cryptography.algorithms.* import dev.whyoleg.cryptography.providers.jdk.algorithms.* import dev.whyoleg.cryptography.random.* +import dev.whyoleg.sweetspi.* import java.security.* import java.util.concurrent.* -private val defaultProvider = lazy { CryptographyProvider.Companion.JDK() } +@ServiceProvider +internal val defaultProvider by lazy { CryptographyProvider.Companion.JDK() } -public val CryptographyProvider.Companion.JDK: CryptographyProvider by defaultProvider +public val CryptographyProvider.Companion.JDK: CryptographyProvider get() = defaultProvider @Suppress("FunctionName") public fun CryptographyProvider.Companion.JDK( @@ -95,7 +97,3 @@ internal class JdkCryptographyProvider( } } as A? } - -internal class JdkCryptographyProviderContainer : CryptographyProviderContainer { - override val provider: Lazy get() = defaultProvider -} diff --git a/cryptography-providers/jdk/src/jvmMain/resources/META-INF/services/dev.whyoleg.cryptography.CryptographyProviderContainer b/cryptography-providers/jdk/src/jvmMain/resources/META-INF/services/dev.whyoleg.cryptography.CryptographyProviderContainer deleted file mode 100644 index b6506cc4..00000000 --- a/cryptography-providers/jdk/src/jvmMain/resources/META-INF/services/dev.whyoleg.cryptography.CryptographyProviderContainer +++ /dev/null @@ -1 +0,0 @@ -dev.whyoleg.cryptography.providers.jdk.JdkCryptographyProviderContainer diff --git a/cryptography-providers/openssl3/api/build.gradle.kts b/cryptography-providers/openssl3/api/build.gradle.kts index 8723cff3..cf99753d 100644 --- a/cryptography-providers/openssl3/api/build.gradle.kts +++ b/cryptography-providers/openssl3/api/build.gradle.kts @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.gradle.tasks.* plugins { id("ckbuild.multiplatform-library") + id("ckbuild.multiplatform-sweetspi") id("ckbuild.use-openssl") } diff --git a/cryptography-providers/openssl3/api/src/commonMain/kotlin/Openssl3CryptographyProvider.kt b/cryptography-providers/openssl3/api/src/commonMain/kotlin/Openssl3CryptographyProvider.kt index fa6741af..b64088fa 100644 --- a/cryptography-providers/openssl3/api/src/commonMain/kotlin/Openssl3CryptographyProvider.kt +++ b/cryptography-providers/openssl3/api/src/commonMain/kotlin/Openssl3CryptographyProvider.kt @@ -9,11 +9,13 @@ import dev.whyoleg.cryptography.algorithms.* import dev.whyoleg.cryptography.algorithms.RSA import dev.whyoleg.cryptography.providers.openssl3.algorithms.* import dev.whyoleg.cryptography.providers.openssl3.internal.cinterop.* +import dev.whyoleg.sweetspi.* import kotlinx.cinterop.* -private val defaultProvider = lazy { Openssl3CryptographyProvider } +@ServiceProvider +internal val defaultProvider by lazy { Openssl3CryptographyProvider } -public val CryptographyProvider.Companion.Openssl3: CryptographyProvider by defaultProvider +public val CryptographyProvider.Companion.Openssl3: CryptographyProvider get() = defaultProvider internal object Openssl3CryptographyProvider : CryptographyProvider() { override val name: String = "OpenSSL3 (${OpenSSL_version(OPENSSL_VERSION_STRING)?.toKString() ?: "unknown"})" @@ -47,8 +49,3 @@ internal object Openssl3CryptographyProvider : CryptographyProvider() { else -> null } as A? } - -@Suppress("DEPRECATION") -@OptIn(ExperimentalStdlibApi::class) -@EagerInitialization -private val initHook = CryptographyProvider.Registry.registerProvider(defaultProvider) diff --git a/cryptography-providers/webcrypto/api/cryptography-provider-webcrypto.klib.api b/cryptography-providers/webcrypto/api/cryptography-provider-webcrypto.klib.api index ae78e392..d8a57532 100644 --- a/cryptography-providers/webcrypto/api/cryptography-provider-webcrypto.klib.api +++ b/cryptography-providers/webcrypto/api/cryptography-provider-webcrypto.klib.api @@ -10,5 +10,5 @@ final val dev.whyoleg.cryptography.providers.webcrypto/WebCrypto // dev.whyoleg. final fun (dev.whyoleg.cryptography/CryptographyProvider.Companion).(): dev.whyoleg.cryptography/CryptographyProvider // dev.whyoleg.cryptography.providers.webcrypto/WebCrypto.|@dev.whyoleg.cryptography.CryptographyProvider.Companion(){}[0] // Targets: [js] -final val dev.whyoleg.cryptography.providers.webcrypto/initHook // dev.whyoleg.cryptography.providers.webcrypto/initHook|{}initHook[0] - final fun (): dynamic // dev.whyoleg.cryptography.providers.webcrypto/initHook.|(){}[0] +final val dev.whyoleg.cryptography.providers.webcrypto/init_dev_whyoleg_cryptography_providers_webcrypto // dev.whyoleg.cryptography.providers.webcrypto/init_dev_whyoleg_cryptography_providers_webcrypto|{}init_dev_whyoleg_cryptography_providers_webcrypto[0] + final fun (): dynamic // dev.whyoleg.cryptography.providers.webcrypto/init_dev_whyoleg_cryptography_providers_webcrypto.|(){}[0] diff --git a/cryptography-providers/webcrypto/build.gradle.kts b/cryptography-providers/webcrypto/build.gradle.kts index 025b7916..71fbf05d 100644 --- a/cryptography-providers/webcrypto/build.gradle.kts +++ b/cryptography-providers/webcrypto/build.gradle.kts @@ -7,6 +7,7 @@ import org.jetbrains.kotlin.gradle.* plugins { id("ckbuild.multiplatform-library") + id("ckbuild.multiplatform-sweetspi") id("ckbuild.multiplatform-provider-tests") } diff --git a/cryptography-providers/webcrypto/src/commonMain/kotlin/WebCryptoCryptographyProvider.kt b/cryptography-providers/webcrypto/src/commonMain/kotlin/WebCryptoCryptographyProvider.kt index d92b5908..43fef899 100644 --- a/cryptography-providers/webcrypto/src/commonMain/kotlin/WebCryptoCryptographyProvider.kt +++ b/cryptography-providers/webcrypto/src/commonMain/kotlin/WebCryptoCryptographyProvider.kt @@ -7,10 +7,12 @@ package dev.whyoleg.cryptography.providers.webcrypto import dev.whyoleg.cryptography.* import dev.whyoleg.cryptography.algorithms.* import dev.whyoleg.cryptography.providers.webcrypto.algorithms.* +import dev.whyoleg.sweetspi.* -internal val defaultProvider = lazy { WebCryptoCryptographyProvider } +@ServiceProvider +internal val defaultProvider by lazy { WebCryptoCryptographyProvider } -public val CryptographyProvider.Companion.WebCrypto: CryptographyProvider by defaultProvider +public val CryptographyProvider.Companion.WebCrypto: CryptographyProvider get() = defaultProvider internal object WebCryptoCryptographyProvider : CryptographyProvider() { override val name: String get() = "WebCrypto" diff --git a/cryptography-providers/webcrypto/src/jsMain/kotlin/WebCryptoCryptographyProvider.js.kt b/cryptography-providers/webcrypto/src/jsMain/kotlin/WebCryptoCryptographyProvider.js.kt index cc68c82e..2ea14b9a 100644 --- a/cryptography-providers/webcrypto/src/jsMain/kotlin/WebCryptoCryptographyProvider.js.kt +++ b/cryptography-providers/webcrypto/src/jsMain/kotlin/WebCryptoCryptographyProvider.js.kt @@ -3,14 +3,3 @@ */ package dev.whyoleg.cryptography.providers.webcrypto - -import dev.whyoleg.cryptography.* - -// declaration should be public for EagerInitialization to work -// Deprecated to make it `internal`ish -@Suppress("DEPRECATION") -@OptIn(ExperimentalStdlibApi::class, ExperimentalJsExport::class) -@EagerInitialization -@JsExport -@Deprecated("", level = DeprecationLevel.HIDDEN) -public val initHook: dynamic = CryptographyProvider.Registry.registerProvider(defaultProvider) diff --git a/cryptography-providers/webcrypto/src/wasmJsMain/kotlin/WebCryptoCryptographyProvider.wasmJs.kt b/cryptography-providers/webcrypto/src/wasmJsMain/kotlin/WebCryptoCryptographyProvider.wasmJs.kt index 478cec0f..2ea14b9a 100644 --- a/cryptography-providers/webcrypto/src/wasmJsMain/kotlin/WebCryptoCryptographyProvider.wasmJs.kt +++ b/cryptography-providers/webcrypto/src/wasmJsMain/kotlin/WebCryptoCryptographyProvider.wasmJs.kt @@ -3,10 +3,3 @@ */ package dev.whyoleg.cryptography.providers.webcrypto - -import dev.whyoleg.cryptography.* - -@Suppress("DEPRECATION") -@OptIn(ExperimentalStdlibApi::class) -@EagerInitialization -internal val initHook = CryptographyProvider.Registry.registerProvider(defaultProvider) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b106815a..227ce2ae 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,8 @@ [versions] kotlin = "2.0.20" +ksp = "2.0.20-1.0.24" +sweetspi = "0.1.2" # kotlin/kotlinx kotlin-dokka = "1.9.20" @@ -30,6 +32,8 @@ kotlinx-bcv-gradle-plugin = { module = "org.jetbrains.kotlinx:binary-compatibili kotlinx-kover-gradle-plugin = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kotlinx-kover" } android-gradle-plugin = { module = "com.android.tools.build:gradle", version.ref = "android" } maven-publish-gradle-plugin = { module = "com.vanniktech:gradle-maven-publish-plugin", version.ref = "maven-publish" } +ksp-gradle-plugin = { module = "com.google.devtools.ksp:symbol-processing-gradle-plugin", version.ref = "ksp" } +sweetspi-gradle-plugin = { module = "dev.whyoleg.sweetspi:sweetspi-gradle-plugin", version.ref = "sweetspi" } apache-commons-compress = { module = "org.apache.commons:commons-compress", version.ref = "apache-commons-compress" } @@ -63,3 +67,5 @@ kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref kotlin-plugin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } kotlin-dokka = { id = "org.jetbrains.dokka", version.ref = "kotlin-dokka" } android-library = { id = "com.android.library", version.ref = "android" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +sweetspi = { id = "dev.whyoleg.sweetspi", version.ref = "sweetspi" } \ No newline at end of file