--- a/core/build.gradle.kts Wed Mar 12 21:35:19 2025 -0400
+++ b/core/build.gradle.kts Thu Apr 03 16:08:10 2025 -0400
@@ -55,6 +55,7 @@
commonMain.dependencies {
implementation(libs.okio)
implementation(libs.kotlinx.coroutines)
+ implementation(libs.kotlinx.serialization.json)
}
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core/src/commonMain/kotlin/licensee/LicenseeLicenseInfoRepository.kt Thu Apr 03 16:08:10 2025 -0400
@@ -0,0 +1,121 @@
+/*
+ * AboutOss is an utility library to retrieve and display
+ * opensource licenses in Android applications.
+ *
+ * Copyright (C) 2023 by Frederic-Charles Barthelery.
+ *
+ * This file is part of AboutOss.
+ *
+ * AboutOss is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AboutOss is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AboutOss. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.geekorum.aboutoss.core.licensee
+
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+import kotlinx.serialization.ExperimentalSerializationApi
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.Json
+import okio.Source
+import okio.buffer
+
+class LicenseeLicenseInfoRepository(
+ private val produceInput: suspend () -> Source,
+ private val mainCoroutineDispatcher: CoroutineDispatcher,
+ private val ioCoroutineDispatcher: CoroutineDispatcher,
+) {
+
+ private var licensesInfo: Map<String, String>? = null
+
+ suspend fun getLicensesInfo(): Map<String, String> = withContext(mainCoroutineDispatcher) {
+ parseLicenses()
+ checkNotNull(licensesInfo)
+ }
+
+ suspend fun getLicenseFor(dependency: String): String = withContext(mainCoroutineDispatcher) {
+ parseLicenses()
+ checkNotNull(licensesInfo).let {
+ return@withContext it[dependency] ?: error("Dependency not found")
+ }
+ }
+
+ @OptIn(ExperimentalSerializationApi::class)
+ private suspend fun parseLicenses() = withContext(mainCoroutineDispatcher) {
+ if (licensesInfo == null) {
+ val licenses = withContext(ioCoroutineDispatcher) {
+ LicenseeParser(produceInput()).use {
+ it.readLicensee()
+ }
+ }
+ licensesInfo = licenses
+ }
+ }
+}
+
+
+private class LicenseeParser(
+ input: Source
+): AutoCloseable {
+ private val buffered = input.buffer()
+
+ fun readLicensee(): Map<String, String> {
+ val json = Json {
+ ignoreUnknownKeys = true
+ }
+ val items: List<LicenseItem> = json.decodeFromString(buffered.readUtf8())
+
+ return items.associate {
+ val name = it.name ?: "${it.groupId}:${it.artifactId}"
+ val license = it.spdxLicenses.firstNotNullOfOrNull {
+ "${it.name}\n\n${it.url}"
+ } ?: it.unknownLicenses.firstNotNullOf {
+ "${it.name}\n\n${it.url}"
+ }
+ name to license
+ }
+ }
+
+ override fun close() {
+ buffered.close()
+ }
+}
+
+
+@Serializable
+private data class LicenseItem(
+ val groupId: String,
+ val artifactId: String,
+ val version: String,
+ val spdxLicenses: List<SpdxLicense> = emptyList(),
+ val unknownLicenses: List<UnknownLicense> = emptyList(),
+ val name: String? = null,
+ val scm: Scm? = null,
+)
+
+@Serializable
+private data class SpdxLicense(
+ val identifier: String,
+ val name: String,
+ val url: String,
+)
+
+@Serializable
+private data class UnknownLicense(
+ val name: String,
+ val url: String
+)
+
+@Serializable
+private data class Scm(
+ val url: String,
+)
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core/src/iosMain/kotlin/licensee/LicenseeLicenseInfoRepository.ios.kt Thu Apr 03 16:08:10 2025 -0400
@@ -0,0 +1,67 @@
+/*
+ * AboutOss is an utility library to retrieve and display
+ * opensource licenses in Android applications.
+ *
+ * Copyright (C) 2023 by Frederic-Charles Barthelery.
+ *
+ * This file is part of AboutOss.
+ *
+ * AboutOss is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AboutOss is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AboutOss. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.geekorum.aboutoss.core.licensee
+
+import kotlinx.cinterop.ExperimentalForeignApi
+import kotlinx.cinterop.addressOf
+import kotlinx.cinterop.usePinned
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.IO
+import okio.Buffer
+import platform.Foundation.NSBundle
+import platform.Foundation.NSData
+import platform.Foundation.NSFileManager
+import platform.posix.memcpy
+
+fun LicenseeLicenseInfoRepository(
+ licenseeResourcePath: String = "compose-resources/app/cash/licensee/artifacts.json",
+ mainCoroutineDispatcher: CoroutineDispatcher = Dispatchers.Main,
+ ioCoroutineDispatcher: CoroutineDispatcher = Dispatchers.IO,
+): LicenseeLicenseInfoRepository {
+ return LicenseeLicenseInfoRepository(
+ produceInput = {
+ val buffer = Buffer()
+ buffer.write(readResources(licenseeResourcePath))
+ buffer
+ },
+ mainCoroutineDispatcher = mainCoroutineDispatcher,
+ ioCoroutineDispatcher = ioCoroutineDispatcher
+ )
+}
+
+
+@OptIn(ExperimentalForeignApi::class)
+private fun readResources(path: String): ByteArray {
+ val data = readData(getPathInBundle(path))
+ return ByteArray(data.length.toInt()).apply {
+ usePinned { memcpy(it.addressOf(0), data.bytes, data.length) }
+ }
+}
+
+private fun getPathInBundle(path: String): String {
+ return NSBundle.mainBundle.resourcePath + "/$path"
+}
+
+private fun readData(path: String): NSData {
+ return NSFileManager.defaultManager().contentsAtPath(path) ?: error("Resources not found with path $path")
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/core/src/main/java/com/geekorum/aboutoss/core/licensee/LicenseeLicenseInfoRepository.android.kt Thu Apr 03 16:08:10 2025 -0400
@@ -0,0 +1,42 @@
+/*
+ * AboutOss is an utility library to retrieve and display
+ * opensource licenses in Android applications.
+ *
+ * Copyright (C) 2023 by Frederic-Charles Barthelery.
+ *
+ * This file is part of AboutOss.
+ *
+ * AboutOss is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AboutOss is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AboutOss. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.geekorum.aboutoss.core.licensee
+
+import android.content.res.AssetManager
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.Dispatchers
+import okio.source
+
+fun LicenseeLicenseInfoRepository(
+ assetManager: AssetManager,
+ licenseeAssetsPath: String = "app/cash/licensee/artifacts.json",
+ mainCoroutineDispatcher: CoroutineDispatcher = Dispatchers.Main,
+ ioCoroutineDispatcher: CoroutineDispatcher = Dispatchers.IO,
+): LicenseeLicenseInfoRepository {
+ return LicenseeLicenseInfoRepository(
+ produceInput = {
+ assetManager.open(licenseeAssetsPath).source()
+ },
+ mainCoroutineDispatcher = mainCoroutineDispatcher,
+ ioCoroutineDispatcher = ioCoroutineDispatcher
+ )
+}
--- a/gradle/libs.versions.toml Wed Mar 12 21:35:19 2025 -0400
+++ b/gradle/libs.versions.toml Thu Apr 03 16:08:10 2025 -0400
@@ -27,7 +27,8 @@
espresso-core = "3.5.1"
appcompat = "1.6.1"
okio = "3.3.0"
-kotlinx-coroutines = "1.6.4"
+kotlinx-coroutines = "1.10.1"
+kotlinx-serialization = "1.8.1"
androidx-activity = "1.7.0"
androidx-navigation = "2.5.3"
androidx-compose-bom = "2023.04.00"
@@ -62,6 +63,8 @@
androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
+kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
+
[plugins]
com-android-application = { id = "com.android.application", version.ref = "com-android-application" }
@@ -69,6 +72,7 @@
org-jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "org-jetbrains-kotlin" }
org-jetbrains-kotlin-compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "org-jetbrains-kotlin" }
google-gms-oss-license = { id = "com.google.android.gms.oss-licenses-plugin", version = "0.10.6" }
+org-jetbrains-kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "org-jetbrains-kotlin" }
[bundles]