diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml index f0f5a49..d769c4d 100644 --- a/.github/workflows/create_release.yml +++ b/.github/workflows/create_release.yml @@ -10,12 +10,12 @@ jobs: create-github-release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Create Release Notes run: ./gradlew --quiet getChangelog --no-header > ./RELEASE_NOTES.md - name: Create Release id: create_release - uses: chrimaeon/github-create-release-action@0.2.0 + uses: chrimaeon/github-create-release-action@v1 env: GITHUB_TOKEN: ${{ github.token }} with: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9eb4e4f..6ae16a5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,13 +13,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-java@v2 + - uses: actions/checkout@v3 + - uses: actions/setup-java@v3 with: distribution: zulu java-version: 11 - name: Gradle Cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: | ~/.gradle/caches/modules-* @@ -27,7 +27,7 @@ jobs: ~/.gradle/caches/build-cache-* key: gradle-${{ hashFiles('**/build.gradle.kts', '**/Deps.kt') }} - name: Gradle Wrapper Cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.gradle/wrapper key: gradle-wrapper-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} @@ -39,7 +39,7 @@ jobs: - name: Archive Test results if: ${{ failure() }} - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: test-results path: | @@ -47,4 +47,4 @@ jobs: build/test-results/* - name: Upload Codecov - uses: codecov/codecov-action@v2 + uses: codecov/codecov-action@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 50686b6..5b389b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,22 +13,31 @@ ### Security -## [4.4.0] +## [4.5.0] ### Added -- [SPDX License Identifier](https://spdx.org/licenses/) for various reports +- Better support for Android Variants ### Changed -- HTML and Markdown reports merge licenses with a more sophisticated algorithm +- Internal handling of the license mappings ### Deprecated ### Removed ### Fixed -- CSV Reporter reports all licenses not only the first one ### Security +## [4.4.0] +### Added +- [SPDX License Identifier](https://spdx.org/licenses/) for various reports + +### Changed +- HTML and Markdown reports merge licenses with a more sophisticated algorithm + +### Fixed +- CSV Reporter reports all licenses not only the first one + ## [4.3.0] ### Changed - add maven coordinates to Library model @@ -75,4 +84,4 @@ ## [3.1.0] ### Changed - All public properties are now provided Properties -- Use Kotlin Serialization instead of Moshi \ No newline at end of file +- Use Kotlin Serialization instead of Moshi diff --git a/README.md b/README.md index 792e344..38b6940 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ This Gradle plugin provides tasks to generate a file with the licenses used from ```kotlin plugins { - id("com.cmgapps.licenses") version "4.4.0" + id("com.cmgapps.licenses") version "4.5.0" } ``` @@ -28,7 +28,7 @@ plugins { ```groovy plugins { - id 'com.cmgapps.licenses' version '4.4.0' + id 'com.cmgapps.licenses' version '4.5.0' } ``` @@ -46,7 +46,7 @@ buildscript { } } dependencies { - classpath("com.cmgapps:gradle-licenses-plugin:4.4.0") + classpath("com.cmgapps:gradle-licenses-plugin:4.5.0") } } @@ -65,7 +65,7 @@ buildscript { } } dependencies { - classpath 'com.cmgapps:gradle-licenses-plugin:4.4.0' + classpath 'com.cmgapps:gradle-licenses-plugin:4.5.0' } } diff --git a/build.gradle.kts b/build.gradle.kts index a7b4155..28d7797 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,6 +6,7 @@ import com.cmgapps.gradle.logResults import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask +import com.github.benmanes.gradle.versions.updates.gradle.GradleReleaseChannel import kotlinx.kover.api.VerificationValueType.COVERED_LINES_PERCENTAGE import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.util.Date @@ -16,18 +17,13 @@ plugins { `java-gradle-plugin` `maven-publish` signing - id("com.github.ben-manes.versions") version Deps.Plugins.versionsVersion - kotlin("jvm") version Deps.kotlinVersion - id("com.gradle.plugin-publish") version Deps.Plugins.pluginPublishVersion - id("org.jetbrains.dokka") version Deps.Plugins.dokkaVersion - kotlin("plugin.serialization") version Deps.kotlinVersion - id("org.jetbrains.changelog") version Deps.Plugins.changelogPluginVersion - id("org.jetbrains.kotlinx.kover") version Deps.Plugins.koverVersion -} - -repositories { - mavenCentral() - google() + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.versions) + alias(libs.plugins.gradle.pluginPublish) + alias(libs.plugins.jetbrains.dokka) + alias(libs.plugins.jetbrains.changelog) + alias(libs.plugins.kotlinx.kover) } val functionalTestSourceSet: SourceSet = sourceSets.create("functionalTest") { @@ -221,7 +217,7 @@ tasks { "Built-Date" to Date(), "Built-JDK" to System.getProperty("java.version"), "Built-Gradle" to gradle.gradleVersion, - "Built-Kotlin" to Deps.kotlinVersion + "Built-Kotlin" to libs.versions.kotlin ) ) } @@ -230,6 +226,8 @@ tasks { named("dependencyUpdates") { revision = "release" + gradleReleaseChannel = GradleReleaseChannel.CURRENT.id + rejectVersionIf { listOf("alpha", "beta", "rc", "cr", "m", "preview") .map { qualifier -> Regex("(?i).*[.-]$qualifier[.\\d-]*") } @@ -244,7 +242,7 @@ tasks { withType { kotlinOptions { - freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" + freeCompilerArgs = freeCompilerArgs + "-opt-in=kotlin.RequiresOptIn" jvmTarget = "1.8" } } @@ -267,9 +265,10 @@ tasks { doLast { val content = readmeFile.readText() - val oldVersion = """id\("com.cmgapps.licenses"\) version "(.*)"""".toRegex(RegexOption.MULTILINE).find(content)?.let { - it.groupValues[1] - } ?: error("Cannot find oldVersion") + val oldVersion = + """id\("com.cmgapps.licenses"\) version "(.*)"""".toRegex(RegexOption.MULTILINE).find(content)?.let { + it.groupValues[1] + } ?: error("Cannot find oldVersion") logger.info("Updating README.md version $oldVersion to $version") @@ -293,34 +292,35 @@ tasks { } } +@Suppress("UnstableApiUsage") dependencies { - compileOnly(Deps.androidGradlePlugin) - compileOnly(Deps.kotlinMultiplatformPlugin) - - val kotlinReflect = kotlin("reflect", Deps.kotlinVersion) + compileOnly(libs.android.gradlePlugin) + compileOnly(libs.kotlin.multiplatformPlugin) // Necessary to bump a transitive dependency. - compileOnly(kotlinReflect) + compileOnly(libs.kotlin.reflect) - implementation(kotlin("stdlib-jdk8", Deps.kotlinVersion)) - implementation(Deps.mavenModel) - implementation(Deps.mavenArtifact) - implementation(Deps.kotlinSerialization) - implementation(Deps.apacheCommonsCsv) + implementation(libs.kotlin.stdlib.jdk8) + implementation(libs.maven.model) + implementation(libs.maven.artifact) + implementation(libs.kotlin.serialization) + implementation(libs.apache.commonsCsv) - ktlint(Deps.ktlint) + ktlint(libs.ktlint) - testImplementation(Deps.jUnit) { + testImplementation(libs.jUnit) { exclude(group = "org.hamcrest") } - testImplementation(Deps.hamcrest) - testImplementation(kotlinReflect) - testImplementation(Deps.mockitoKotlin) + testImplementation(libs.hamcrest) + testImplementation(libs.kotlin.reflect) + testImplementation(libs.mockito.kotlin) - "functionalTestImplementation"(Deps.jUnit) { + "functionalTestImplementation"(libs.jUnit) { exclude(group = "org.hamcrest") } - "functionalTestImplementation"(Deps.kotlinMultiplatformPlugin) - "functionalTestImplementation"(Deps.hamcrest) + "functionalTestImplementation"(libs.kotlin.multiplatformPlugin) + "functionalTestImplementation"(libs.hamcrest) "functionalTestImplementation"(gradleTestKit()) - "functionalTestImplementation"(kotlinReflect) + "functionalTestImplementation"(libs.kotlin.reflect) + "functionalTestImplementation"(libs.xmlunit.core) + "functionalTestImplementation"(libs.xmlunit.matchers) } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index b189d11..9db26d3 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,24 +1,16 @@ /* * Copyright (c) 2019. Christian Grach * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { `kotlin-dsl` } -tasks.withType { +tasks.withType { kotlinOptions { freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" } diff --git a/buildSrc/src/main/kotlin/Deps.kt b/buildSrc/src/main/kotlin/Deps.kt deleted file mode 100644 index 237e0fd..0000000 --- a/buildSrc/src/main/kotlin/Deps.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2019. Christian Grach - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -object Deps { - const val kotlinVersion = "1.6.20" - - object Plugins { - const val dokkaVersion = "1.6.10" - const val changelogPluginVersion = "1.3.1" - const val pluginPublishVersion = "0.21.0" - const val versionsVersion = "0.42.0" - const val koverVersion = "0.5.0" - } - - const val androidGradlePlugin = "com.android.tools.build:gradle:7.1.2" - const val kotlinMultiplatformPlugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion" - const val apacheCommonsCsv = "org.apache.commons:commons-csv:1.9.0" - const val mavenModel = "org.apache.maven:maven-model:3.8.5" - const val mavenArtifact = "org.apache.maven:maven-artifact:3.8.5" - const val jUnit = "org.junit.jupiter:junit-jupiter:5.8.2" - const val hamcrest = "org.hamcrest:hamcrest:2.2" - const val ktlint = "com.pinterest:ktlint:0.45.1" - const val kotlinSerialization = "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2" - const val mockitoKotlin = "org.mockito.kotlin:mockito-kotlin:4.0.0" -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..1920514 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,28 @@ +[versions] +kotlin = "1.7.0" +xmlunit = "2.9.0" + +[plugins] +kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +versions = "com.github.ben-manes.versions:0.42.0" +gradle-pluginPublish = "com.gradle.plugin-publish:0.21.0" +kotlinx-kover = "org.jetbrains.kotlinx.kover:0.5.1" +jetbrains-dokka = "org.jetbrains.dokka:1.6.21" +jetbrains-changelog = "org.jetbrains.changelog:1.3.1" + +[libraries] +android-gradlePlugin = "com.android.tools.build:gradle:7.2.1" +kotlin-multiplatformPlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } +kotlin-serialization = "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.3" +kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } +kotlin-stdlib-jdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" } +apache-commonsCsv = "org.apache.commons:commons-csv:1.9.0" +maven-model = "org.apache.maven:maven-model:3.8.5" +maven-artifact = "org.apache.maven:maven-artifact:3.8.6" +jUnit = "org.junit.jupiter:junit-jupiter:5.8.2" +hamcrest = "org.hamcrest:hamcrest:2.2" +ktlint = "com.pinterest:ktlint:0.45.2" +mockito-kotlin = "org.mockito.kotlin:mockito-kotlin:4.0.0" +xmlunit-core = { module = "org.xmlunit:xmlunit-core", version.ref = "xmlunit" } +xmlunit-matchers = { module = "org.xmlunit:xmlunit-matchers", version.ref = "xmlunit" } diff --git a/pom.properties b/pom.properties index f281c78..53a3638 100644 --- a/pom.properties +++ b/pom.properties @@ -4,7 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 # group=com.cmgapps -versionName=4.4.0 +versionName=4.5.0 pomName=Gradle Licenses Plugin pomArtifactId=gradle-licenses-plugin pomDescription=Gradle plugin that provides a task to generate a license report for the dependencies used in your project Java/Kotlin project. diff --git a/settings.gradle.kts b/settings.gradle.kts index c8210d7..ba72708 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,17 +1,25 @@ /* -* Copyright (c) 2019. Christian Grach -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ + * Copyright (c) 2019. Christian Grach + * + * SPDX-License-Identifier: Apache-2.0 + */ + +@file:Suppress("UnstableApiUsage") + +pluginManagement { + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + } +} rootProject.name = "Gradle Licenses Plugin" diff --git a/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginAndroidShould.kt b/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginAndroidShould.kt index dee3a33..948b49e 100644 --- a/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginAndroidShould.kt +++ b/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginAndroidShould.kt @@ -1,17 +1,7 @@ /* * Copyright (c) 2019. Christian Grach * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * SPDX-License-Identifier: Apache-2.0 */ package com.cmgapps.license @@ -25,13 +15,19 @@ import org.hamcrest.Matchers.`is` import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.io.TempDir +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.Arguments.arguments +import org.junit.jupiter.params.provider.MethodSource import java.io.File import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths import java.util.Properties +import java.util.stream.Stream -const val AGP = "com.android.tools.build:gradle:3.5.3" +const val AGP_7_x = "com.android.tools.build:gradle:7.2.1" +const val AGP_4_x = "com.android.tools.build:gradle:4.0.1" class LicensePluginAndroidShould { @@ -52,11 +48,9 @@ class LicensePluginAndroidShould { ) pluginClasspath = Properties().run { load(pluginClasspathResource) - getProperty("implementation-classpath") - .split(':') - .joinToString(", ") { - "'$it'" - } + getProperty("implementation-classpath").split(':').joinToString(", ") { + "'$it'" + } } buildFile = Files.createFile(Paths.get(testProjectDir.toString(), "build.gradle")).toFile() @@ -67,11 +61,11 @@ class LicensePluginAndroidShould { buildFile + """ buildscript { repositories { - jcenter() + mavenCentral() google() } dependencies { - classpath "$AGP" + classpath "$AGP_7_x" classpath files($pluginClasspath) } } @@ -80,77 +74,104 @@ class LicensePluginAndroidShould { """.trimIndent() - gradleRunner = GradleRunner.create() - .withProjectDir(testProjectDir.toFile()) + gradleRunner = GradleRunner.create().withProjectDir(testProjectDir.toFile()) } - @Test - fun `generate licenses buildType report`() { - buildFile + """ + @ParameterizedTest(name = "${ParameterizedTest.DISPLAY_NAME_PLACEHOLDER} - taskName = {0}, AGP = {1}") + @MethodSource("buildTypesAndAgpVersions") + fun `generate licenses buildType report`(taskName: String, agbVersion: String) { + buildFile.write( + """ + buildscript { + repositories { + mavenCentral() + google() + } + dependencies { + classpath "$agbVersion" + classpath files($pluginClasspath) + } + } + apply plugin: 'com.android.application' + apply plugin: 'com.cmgapps.licenses' + android { compileSdkVersion 28 defaultConfig { applicationId 'com.example' } } - """ - .trimIndent() - - for (taskName in listOf("licenseDebugReport", "licenseReleaseReport")) { + """.trimIndent() + ) - val result = GradleRunner.create() - .withProjectDir(testProjectDir.toFile()) - .withArguments(":$taskName") - .build() + val result = gradleRunner.withArguments(":$taskName").build() - assertThat(result.task(":$taskName")?.outcome, `is`(TaskOutcome.SUCCESS)) - } + assertThat(result.task(":$taskName")?.outcome, `is`(TaskOutcome.SUCCESS)) } - @Test - fun `generate licenses variant report`() { + @ParameterizedTest(name = "${ParameterizedTest.DISPLAY_NAME_PLACEHOLDER} - taskName = {0}") + @MethodSource("productFlavorsAndCsv") + fun `generate licenses variant report`(taskName: String, licensesAsCsvExpected: String) { buildFile + """ - android { - compileSdkVersion 28 - defaultConfig { - applicationId 'com.example' + repositories { + maven { + url '$mavenRepoUrl' + } } - - flavorDimensions "version" - productFlavors { - demo { - dimension "version" + android { + compileSdkVersion 28 + defaultConfig { + applicationId 'com.example' } - full { - dimension "version" + + flavorDimensions "version", "store" + productFlavors { + demo { + dimension "version" + } + full { + dimension "version" + } + google { + dimension "store" + } + amazon { + dimension "store" + } } } - } + + licenses { + reports { + html.enabled = false + csv.enabled = true + } + } + dependencies { + implementation 'group:name:1.0.0' + demoImplementation 'group:noname:1.0.0' + fullImplementation 'group:multilicenses:1.0.0' + googleImplementation 'group:foo:1.0.0' + amazonImplementation 'group:bar:1.0.0' + releaseImplementation 'com.squareup.retrofit2:retrofit:2.3.0' + debugImplementation 'group:zet:1.0.0' + } """.trimIndent() - val tasks = listOf( - "licenseDemoDebugReport", - "licenseFullDebugReport", - "licenseDemoReleaseReport", - "licenseFullReleaseReport" - ) - - for (taskName in tasks) { - val result = gradleRunner.withArguments(":$taskName") - .build() + gradleRunner + .withArguments(":$taskName") + .build() - assertThat(result.task(":$taskName")?.outcome, `is`(TaskOutcome.SUCCESS)) - } + assertThat(File("$reportFolder/$taskName/licenses.csv").readText(), `is`(licensesAsCsvExpected)) } @Test fun `generate Report for selected configuration`() { buildFile + """ - import com.cmgapps.license.OutputType repositories { maven { - url '$mavenRepoUrl' - } + url '$mavenRepoUrl' + } } android { compileSdkVersion 28 @@ -171,18 +192,13 @@ class LicensePluginAndroidShould { releaseImplementation 'com.squareup.retrofit2:retrofit:2.3.0' } """.trimIndent() + gradleRunner.withArguments(":licenseDebugReport").build() assertThat( File("$reportFolder/licenseDebugReport/licenses.txt").readText().trim(), `is`( - "Licenses\n" + - "├─ Fake dependency name:1.0.0\n" + - "│ ├─ License: Some license\n" + - "│ └─ URL: http://website.tld/\n" + - "└─ group:noname:1.0.0\n" + - " ├─ License: Some license\n" + - " └─ URL: http://website.tld/" + "Licenses\n" + "├─ Fake dependency name:1.0.0\n" + "│ ├─ License: Some license\n" + "│ └─ URL: http://website.tld/\n" + "└─ group:noname:1.0.0\n" + " ├─ License: Some license\n" + " └─ URL: http://website.tld/" ) ) } @@ -193,11 +209,11 @@ class LicensePluginAndroidShould { """ buildscript { repositories { - jcenter() + mavenCentral() google() } dependencies { - classpath "$AGP" + classpath "$AGP_7_x" classpath files($pluginClasspath) } } @@ -222,11 +238,11 @@ class LicensePluginAndroidShould { """ buildscript { repositories { - jcenter() + mavenCentral() google() } dependencies { - classpath "$AGP" + classpath "$AGP_7_x" classpath files($pluginClasspath) } } @@ -244,4 +260,113 @@ class LicensePluginAndroidShould { assertThat(result.task(taskName)?.outcome, `is`(TaskOutcome.SUCCESS)) } + + companion object { + @JvmStatic + fun buildTypesAndAgpVersions(): Stream = + listOf("licenseDebugReport", "licenseReleaseReport").cartesianProduct(listOf(AGP_4_x, AGP_7_x)) + + @JvmStatic + fun productFlavorsAndCsv(): Stream = Stream.of( + arguments( + "licenseDemoGoogleDebugReport", + LICENSE_DEMO_GOOGLE_DEBUG_CSV.replace("\n", "\r\n"), + ), + arguments( + "licenseDemoAmazonDebugReport", + LICENSE_DEMO_AMAZON_DEBUG_CSV.replace("\n", "\r\n"), + ), + arguments( + "licenseFullGoogleDebugReport", + LICENSE_FULL_GOOGLE_DEBUG_CSV.replace("\n", "\r\n"), + ), + arguments( + "licenseFullAmazonDebugReport", + LICENSE_FULL_AMAZON_DEBUG_CSV.replace("\n", "\r\n"), + ), + arguments( + "licenseDemoGoogleReleaseReport", + LICENSE_DEMO_GOOGLE_RELEASE_CSV.replace("\n", "\r\n"), + ), + arguments( + "licenseDemoAmazonReleaseReport", + LICENSE_DEMO_AMAZON_RELEASE_CSV.replace("\n", "\r\n"), + ), + arguments( + "licenseFullGoogleReleaseReport", + LICENSE_FULL_GOOGLE_RELEASE_CSV.replace("\n", "\r\n"), + ), + arguments( + "licenseFullAmazonReleaseReport", + LICENSE_FULL_AMAZON_RELEASE_CSV.replace("\n", "\r\n"), + ), + ) + } } + +internal fun List.cartesianProduct(other: List): Stream = this.flatMap { s1 -> + other.map { s2 -> + arguments(s1, s2) + } +}.stream() + +const val LICENSE_DEMO_GOOGLE_DEBUG_CSV = + """Name,Version,MavenCoordinates,Description,SPDX-License-Identifier,License Name,License Url +Fake dependency name,1.0.0,group:name:1.0.0,Fake dependency description,,Some license,http://website.tld/ +Foo,1.0.0,group:foo:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Zet,1.0.0,group:zet:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +,1.0.0,group:noname:1.0.0,Fake dependency description,,Some license,http://website.tld/ +""" +const val LICENSE_DEMO_AMAZON_DEBUG_CSV = + """Name,Version,MavenCoordinates,Description,SPDX-License-Identifier,License Name,License Url +Bar,1.0.0,group:bar:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Fake dependency name,1.0.0,group:name:1.0.0,Fake dependency description,,Some license,http://website.tld/ +Zet,1.0.0,group:zet:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +,1.0.0,group:noname:1.0.0,Fake dependency description,,Some license,http://website.tld/ +""" +const val LICENSE_FULL_GOOGLE_DEBUG_CSV = + """Name,Version,MavenCoordinates,Description,SPDX-License-Identifier,License Name,License Url +Fake dependency name,1.0.0,group:name:1.0.0,Fake dependency description,,Some license,http://website.tld/ +Foo,1.0.0,group:foo:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Multi License,1.0.0,group:multilicenses:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Multi License,1.0.0,group:multilicenses:1.0.0,Fake dependency description,BSD-2-Clause,BSD-2-Clause,https://opensource.org/licenses/BSD-2-Clause +Zet,1.0.0,group:zet:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +""" +const val LICENSE_FULL_AMAZON_DEBUG_CSV = + """Name,Version,MavenCoordinates,Description,SPDX-License-Identifier,License Name,License Url +Bar,1.0.0,group:bar:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Fake dependency name,1.0.0,group:name:1.0.0,Fake dependency description,,Some license,http://website.tld/ +Multi License,1.0.0,group:multilicenses:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Multi License,1.0.0,group:multilicenses:1.0.0,Fake dependency description,BSD-2-Clause,BSD-2-Clause,https://opensource.org/licenses/BSD-2-Clause +Zet,1.0.0,group:zet:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +""" +const val LICENSE_DEMO_GOOGLE_RELEASE_CSV = + """Name,Version,MavenCoordinates,Description,SPDX-License-Identifier,License Name,License Url +Fake dependency name,1.0.0,group:name:1.0.0,Fake dependency description,,Some license,http://website.tld/ +Foo,1.0.0,group:foo:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Retrofit,2.3.0,com.squareup.retrofit2:retrofit:2.3.0,,Apache-2.0,Apache 2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +,1.0.0,group:noname:1.0.0,Fake dependency description,,Some license,http://website.tld/ +""" +const val LICENSE_DEMO_AMAZON_RELEASE_CSV = + """Name,Version,MavenCoordinates,Description,SPDX-License-Identifier,License Name,License Url +Bar,1.0.0,group:bar:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Fake dependency name,1.0.0,group:name:1.0.0,Fake dependency description,,Some license,http://website.tld/ +Retrofit,2.3.0,com.squareup.retrofit2:retrofit:2.3.0,,Apache-2.0,Apache 2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +,1.0.0,group:noname:1.0.0,Fake dependency description,,Some license,http://website.tld/ +""" +const val LICENSE_FULL_GOOGLE_RELEASE_CSV = + """Name,Version,MavenCoordinates,Description,SPDX-License-Identifier,License Name,License Url +Fake dependency name,1.0.0,group:name:1.0.0,Fake dependency description,,Some license,http://website.tld/ +Foo,1.0.0,group:foo:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Multi License,1.0.0,group:multilicenses:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Multi License,1.0.0,group:multilicenses:1.0.0,Fake dependency description,BSD-2-Clause,BSD-2-Clause,https://opensource.org/licenses/BSD-2-Clause +Retrofit,2.3.0,com.squareup.retrofit2:retrofit:2.3.0,,Apache-2.0,Apache 2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +""" +const val LICENSE_FULL_AMAZON_RELEASE_CSV = + """Name,Version,MavenCoordinates,Description,SPDX-License-Identifier,License Name,License Url +Bar,1.0.0,group:bar:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Fake dependency name,1.0.0,group:name:1.0.0,Fake dependency description,,Some license,http://website.tld/ +Multi License,1.0.0,group:multilicenses:1.0.0,Fake dependency description,Apache-2.0,Apache-2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +Multi License,1.0.0,group:multilicenses:1.0.0,Fake dependency description,BSD-2-Clause,BSD-2-Clause,https://opensource.org/licenses/BSD-2-Clause +Retrofit,2.3.0,com.squareup.retrofit2:retrofit:2.3.0,,Apache-2.0,Apache 2.0,http://www.apache.org/licenses/LICENSE-2.0.txt +""" diff --git a/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginJavaShould.kt b/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginJavaShould.kt index 654c18d..915715f 100644 --- a/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginJavaShould.kt +++ b/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginJavaShould.kt @@ -59,7 +59,7 @@ class LicensePluginJavaShould { .withPluginClasspath() } - @ParameterizedTest(name = "{displayName} - Gradle Version={0}") + @ParameterizedTest(name = "${ParameterizedTest.DISPLAY_NAME_PLACEHOLDER} - Gradle Version = {0}") @ValueSource(strings = ["6.8", "6.9", "7.0", "7.1", "7.2", "7.3", "7.4"]) fun `apply Licenses plugin to various Gradle versions`(version: String) { val result = gradleRunner diff --git a/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginMultiplatformShould.kt b/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginMultiplatformShould.kt index c165c0d..8897e38 100644 --- a/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginMultiplatformShould.kt +++ b/src/functionalTest/kotlin/com/cmgapps/license/LicensePluginMultiplatformShould.kt @@ -67,7 +67,7 @@ class LicensePluginMultiplatformShould { buildFile + """ buildscript { repositories { - jcenter() + mavenCentral() google() } dependencies { diff --git a/src/functionalTest/kotlin/com/cmgapps/license/XmlValidationShould.kt b/src/functionalTest/kotlin/com/cmgapps/license/XmlValidationShould.kt new file mode 100644 index 0000000..23b376b --- /dev/null +++ b/src/functionalTest/kotlin/com/cmgapps/license/XmlValidationShould.kt @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2022. Christian Grach + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.cmgapps.license + +import com.cmgapps.license.util.plus +import org.gradle.testkit.runner.GradleRunner +import org.hamcrest.MatcherAssert.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.io.TempDir +import org.xmlunit.builder.Input +import org.xmlunit.matchers.ValidationMatcher.valid +import java.net.URL +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths + +class XmlValidationShould { + + @TempDir + lateinit var testProjectDir: Path + + @Test + fun validateSchema() { + val reportFolder = "$testProjectDir/build/reports/licenses/licenseReport" + val mavenRepoUrl = javaClass.getResource("/maven")!!.toString() + Files.createFile(Paths.get(testProjectDir.toString(), "build.gradle")).toFile() + """ + plugins { + id("java") + id("com.cmgapps.licenses") + } + + repositories { + maven { + url '$mavenRepoUrl' + } + } + + licenses { + reports { + html.enabled = false + xml.enabled = true + } + } + + dependencies { + implementation 'group:multilicenses:1.0.0' + implementation 'group:name:1.0.0' + } + """.trimIndent() + + GradleRunner.create() + .withProjectDir(testProjectDir.toFile()) + .withArguments(":licenseReport") + .withPluginClasspath() + .build() + + assertThat( + Input.fromFile("$reportFolder/licenses.xml"), + valid(Input.fromURL(URL("https://www.cmgapps.com/xsd/licenses.xsd"))) + ) + } +} diff --git a/src/functionalTest/resources/maven/group/bar/1.0.0/bar-1.0.0.aar b/src/functionalTest/resources/maven/group/bar/1.0.0/bar-1.0.0.aar new file mode 100644 index 0000000..e69de29 diff --git a/src/functionalTest/resources/maven/group/bar/1.0.0/bar-1.0.0.pom b/src/functionalTest/resources/maven/group/bar/1.0.0/bar-1.0.0.pom new file mode 100644 index 0000000..6bf8321 --- /dev/null +++ b/src/functionalTest/resources/maven/group/bar/1.0.0/bar-1.0.0.pom @@ -0,0 +1,38 @@ + + + + + + 4.0.0 + group + bar + 1.0.0 + aar + + + Bar + Fake dependency description + https://github.com/user/repo + 2017 + + + Apache-2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + id + name + + + + + + scm:git@github.com:user/repo.git + scm:git@github.com:user/repo.git + https://github.com/user/repo.git + + diff --git a/src/functionalTest/resources/maven/group/foo/1.0.0/foo-1.0.0.aar b/src/functionalTest/resources/maven/group/foo/1.0.0/foo-1.0.0.aar new file mode 100644 index 0000000..e69de29 diff --git a/src/functionalTest/resources/maven/group/foo/1.0.0/foo-1.0.0.pom b/src/functionalTest/resources/maven/group/foo/1.0.0/foo-1.0.0.pom new file mode 100644 index 0000000..ce66dfa --- /dev/null +++ b/src/functionalTest/resources/maven/group/foo/1.0.0/foo-1.0.0.pom @@ -0,0 +1,38 @@ + + + + + + 4.0.0 + group + foo + 1.0.0 + aar + + + Foo + Fake dependency description + https://github.com/user/repo + 2017 + + + Apache-2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + id + name + + + + + + scm:git@github.com:user/repo.git + scm:git@github.com:user/repo.git + https://github.com/user/repo.git + + diff --git a/src/functionalTest/resources/maven/group/multilicenses/1.0.0/multilicenses-1.0.0.aar b/src/functionalTest/resources/maven/group/multilicenses/1.0.0/multilicenses-1.0.0.aar new file mode 100644 index 0000000..e69de29 diff --git a/src/functionalTest/resources/maven/group/multilicenses/1.0.0/multilicenses-1.0.0.pom b/src/functionalTest/resources/maven/group/multilicenses/1.0.0/multilicenses-1.0.0.pom new file mode 100644 index 0000000..4ec3593 --- /dev/null +++ b/src/functionalTest/resources/maven/group/multilicenses/1.0.0/multilicenses-1.0.0.pom @@ -0,0 +1,42 @@ + + + + + + 4.0.0 + group + multilicenses + 1.0.0 + aar + + + Multi License + Fake dependency description + https://github.com/user/repo + 2017 + + + Apache-2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + BSD-2-Clause + https://opensource.org/licenses/BSD-2-Clause + + + + + id + name + + + + + + scm:git@github.com:user/repo.git + scm:git@github.com:user/repo.git + https://github.com/user/repo.git + + diff --git a/src/functionalTest/resources/maven/group/zet/1.0.0/zet-1.0.0.aar b/src/functionalTest/resources/maven/group/zet/1.0.0/zet-1.0.0.aar new file mode 100644 index 0000000..e69de29 diff --git a/src/functionalTest/resources/maven/group/zet/1.0.0/zet-1.0.0.pom b/src/functionalTest/resources/maven/group/zet/1.0.0/zet-1.0.0.pom new file mode 100644 index 0000000..477287a --- /dev/null +++ b/src/functionalTest/resources/maven/group/zet/1.0.0/zet-1.0.0.pom @@ -0,0 +1,38 @@ + + + + + + 4.0.0 + group + zet + 1.0.0 + aar + + + Zet + Fake dependency description + https://github.com/user/repo + 2017 + + + Apache-2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + id + name + + + + + + scm:git@github.com:user/repo.git + scm:git@github.com:user/repo.git + https://github.com/user/repo.git + + diff --git a/src/main/kotlin/com/cmgapps/license/LicensesPlugin.kt b/src/main/kotlin/com/cmgapps/license/LicensesPlugin.kt index 57e5352..b8d626c 100644 --- a/src/main/kotlin/com/cmgapps/license/LicensesPlugin.kt +++ b/src/main/kotlin/com/cmgapps/license/LicensesPlugin.kt @@ -74,17 +74,50 @@ class LicensesPlugin : Plugin { @JvmStatic private fun configureAndroidProject(project: Project, extension: LicensesExtension) { - getAndroidVariants(project)?.all { androidVariant -> - val taskName = "license" + androidVariant.name.capitalize() + "Report" + // check for AGP 7.0+ 'androidComponent' extension + if (findClass("com.android.build.api.variant.AndroidComponentsExtension") != null) { + configureAgp7Project(project, extension) + } else { + configureApg4Project(project, extension) + } + } + + @JvmStatic + private fun configureAgp7Project(project: Project, extension: LicensesExtension) { + project.logger.info("Using AGP 7.0+ AndroidComponentsExtension") + project.extensions.getByType(com.android.build.api.variant.AndroidComponentsExtension::class.java) + .onVariants { variant -> + val configuration = Action { task -> + task.addBasicConfiguration(extension) + task.variant = variant.name + task.buildType = variant.buildType!! + task.productFlavors = variant.productFlavors.map { it.second } + } + + project.tasks.register( + "license${variant.name.capitalize()}Report", + AndroidLicensesTask::class.java, + configuration, + ) + } + } + @JvmStatic + private fun configureApg4Project(project: Project, extension: LicensesExtension) { + project.logger.info("Using appication/libraryVariants") + getAndroidVariants(project)?.all { androidVariant -> val configuration = Action { task -> task.addBasicConfiguration(extension) task.variant = androidVariant.name task.buildType = androidVariant.buildType.name - task.productFlavors = androidVariant.productFlavors + task.productFlavors = androidVariant.productFlavors.map { it.name } } - project.tasks.register(taskName, AndroidLicensesTask::class.java, configuration) + project.tasks.register( + "license${androidVariant.name.capitalize()}Report", + AndroidLicensesTask::class.java, + configuration, + ) } } @@ -152,3 +185,9 @@ class LicensesPlugin : Plugin { } } } + +fun findClass(fqName: String) = try { + Class.forName(fqName) +} catch (ex: ClassNotFoundException) { + null +} diff --git a/src/main/kotlin/com/cmgapps/license/LicensesTask.kt b/src/main/kotlin/com/cmgapps/license/LicensesTask.kt index 240a89e..04a9e32 100644 --- a/src/main/kotlin/com/cmgapps/license/LicensesTask.kt +++ b/src/main/kotlin/com/cmgapps/license/LicensesTask.kt @@ -6,8 +6,6 @@ package com.cmgapps.license -import com.android.builder.model.ProductFlavor -import com.cmgapps.license.helper.LICENSE_MAP import com.cmgapps.license.model.Library import com.cmgapps.license.model.License import com.cmgapps.license.model.LicenseId @@ -394,7 +392,7 @@ abstract class AndroidLicensesTask : LicensesTask() { lateinit var buildType: String @Internal - lateinit var productFlavors: List + lateinit var productFlavors: List override fun collectDependencies() { @@ -417,16 +415,16 @@ abstract class AndroidLicensesTask : LicensesTask() { productFlavors.forEach { flavor -> // Works for productFlavors and productFlavors with dimensions - if (variant.capitalize().contains(flavor.name.capitalize())) { - project.configurations.find { it.name == "${flavor.name}Compile" }?.let { + if (variant.capitalize().contains(flavor.capitalize())) { + project.configurations.find { it.name == "${flavor}Compile" }?.let { configurations.add(it) } - project.configurations.find { it.name == "${flavor.name}Api" }?.let { + project.configurations.find { it.name == "${flavor}Api" }?.let { configurations.add(it) } - project.configurations.find { it.name == "${flavor.name}Implementation" }?.let { + project.configurations.find { it.name == "${flavor}Implementation" }?.let { configurations.add(it) } } @@ -471,8 +469,11 @@ private fun File.prepare() { createNewFile() } -private fun getLicenseId(licenseUrl: String, licenseName: String): LicenseId = when { - LICENSE_MAP.containsKey(licenseUrl) -> LICENSE_MAP[licenseUrl]!! - LICENSE_MAP.containsKey(licenseName) -> LICENSE_MAP[licenseName]!! - else -> LicenseId.UNKNOWN +private fun getLicenseId(licenseUrl: String, licenseName: String): LicenseId { + val licenseMap = LicenseId.map + return when { + licenseMap.containsKey(licenseUrl) -> licenseMap[licenseUrl]!! + licenseMap.containsKey(licenseName) -> licenseMap[licenseName]!! + else -> LicenseId.UNKNOWN + } } diff --git a/src/main/kotlin/com/cmgapps/license/helper/LicensesHelper.kt b/src/main/kotlin/com/cmgapps/license/helper/LicensesHelper.kt index 3673b0a..aa6f308 100644 --- a/src/main/kotlin/com/cmgapps/license/helper/LicensesHelper.kt +++ b/src/main/kotlin/com/cmgapps/license/helper/LicensesHelper.kt @@ -38,112 +38,6 @@ internal val LicenseId.text: String return this::class.java.getResource("/licenses/${this.filename}")!!.readText() } -/** - * Map License name or URL to license id. - * - * Based on "popular and widely-used or with strong communities" found here: https://opensource.org/licenses/category. - * License text from: https://github.com/github/choosealicense.com/blob/gh-pages/_licenses. - */ -@JvmField -internal val LICENSE_MAP = mapOf( - // Apache License 2.0 - // https://github.com/github/choosealicense.com/blob/gh-pages/_licenses/apache-2.0.txt - "Apache-2.0" to LicenseId.APACHE, - "Apache 2.0" to LicenseId.APACHE, - "Apache v2" to LicenseId.APACHE, - "Apache License 2.0" to LicenseId.APACHE, - "Apache License, Version 2.0" to LicenseId.APACHE, - "The Apache Software License" to LicenseId.APACHE, - "The Apache Software License, Version 2.0" to LicenseId.APACHE, - "http://www.apache.org/licenses/LICENSE-2.0.txt" to LicenseId.APACHE, - "https://www.apache.org/licenses/LICENSE-2.0.txt" to LicenseId.APACHE, - "http://opensource.org/licenses/Apache-2.0" to LicenseId.APACHE, - "https://opensource.org/licenses/Apache-2.0" to LicenseId.APACHE, - "http://www.apache.org/licenses/LICENSE-2.0" to LicenseId.APACHE, - "https://www.apache.org/licenses/LICENSE-2.0" to LicenseId.APACHE, - - // BSD 2-Clause "Simplified" License - // https://github.com/github/choosealicense.com/blob/gh-pages/_licenses/bsd-2-clause.txt - "BSD-2-Clause" to LicenseId.BSD_2, - "BSD 2-Clause \"Simplified\" License" to LicenseId.BSD_2, - "http://opensource.org/licenses/BSD-2-Clause" to LicenseId.BSD_2, - "https://opensource.org/licenses/BSD-2-Clause" to LicenseId.BSD_2, - - // BSD 3-Clause "New" or "Revised" License - // https://github.com/github/choosealicense.com/blob/gh-pages/_licenses/bsd-3-clause.txt - "BSD-3-Clause" to LicenseId.BSD_3, - "BSD 3-Clause \"New\" or \"Revised\" License" to LicenseId.BSD_3, - "http://opensource.org/licenses/BSD-3-Clause" to LicenseId.BSD_3, - "https://opensource.org/licenses/BSD-3-Clause" to LicenseId.BSD_3, - - // Eclipse Public License 2.0 - // https://github.com/github/choosealicense.com/blob/gh-pages/_licenses/epl-2.0.txt - "EPL-2.0" to LicenseId.EPL_2, - "Eclipse Public License 2.0" to LicenseId.EPL_2, - "http://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt" to LicenseId.EPL_2, - "https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt" to LicenseId.EPL_2, - "http://opensource.org/licenses/EPL-2.0" to LicenseId.EPL_2, - "https://opensource.org/licenses/EPL-2.0" to LicenseId.EPL_2, - - // GNU General Public License v2.0 - // https://github.com/github/choosealicense.com/blob/gh-pages/_licenses/gpl-2.0.txt - "GPL-2.0" to LicenseId.GPL_2, - "GNU General Public License v2.0" to LicenseId.GPL_2, - "http://www.gnu.org/licenses/gpl-2.0.txt" to LicenseId.GPL_2, - "https://www.gnu.org/licenses/gpl-2.0.txt" to LicenseId.GPL_2, - "http://opensource.org/licenses/GPL-2.0" to LicenseId.GPL_2, - "https://opensource.org/licenses/GPL-2.0" to LicenseId.GPL_2, - - // GNU General Public License v3.0 - // https://github.com/github/choosealicense.com/blob/gh-pages/_licenses/gpl-3.0.txt - "GPL-3.0" to LicenseId.GPL_3, - "GNU General Public License v3.0" to LicenseId.GPL_3, - "https//www.gnu.org/licenses/gpl-3.0.txt" to LicenseId.GPL_3, - "https://www.gnu.org/licenses/gpl-3.0.txt" to LicenseId.GPL_3, - "http://opensource.org/licenses/GPL-3.0" to LicenseId.GPL_3, - "https://opensource.org/licenses/GPL-3.0" to LicenseId.GPL_3, - - // GNU Lesser General Public License v2.1 - // https://github.com/github/choosealicense.com/blob/gh-pages/_licenses/lgpl-2.1.txt - "LGPL-2.1" to LicenseId.LGPL_2_1, - "GNU Lesser General Public License v2.1" to LicenseId.LGPL_2_1, - "http://www.gnu.org/licenses/lgpl-2.1.txt" to LicenseId.LGPL_2_1, - "https://www.gnu.org/licenses/lgpl-2.1.txt" to LicenseId.LGPL_2_1, - "http://opensource.org/licenses/LGPL-2.1" to LicenseId.LGPL_2_1, - "https://opensource.org/licenses/LGPL-2.1" to LicenseId.LGPL_2_1, - - // GNU Lesser General Public License v3.0 - // https://github.com/github/choosealicense.com/blob/gh-pages/_licenses/lgpl-3.0.txt - "LGPL-3.0" to LicenseId.LGPL_3, - "GNU Lesser General Public License v3.0" to LicenseId.LGPL_3, - "http://www.gnu.org/licenses/lgpl-3.0.txt" to LicenseId.LGPL_3, - "https://www.gnu.org/licenses/lgpl-3.0.txt" to LicenseId.LGPL_3, - "http://opensource.org/licenses/LGPL-3.0" to LicenseId.LGPL_3, - "https://opensource.org/licenses/LGPL-3.0" to LicenseId.LGPL_3, - - // MIT License - // https://github.com/github/choosealicense.com/blob/gh-pages/_licenses/mit.txt - "MIT" to LicenseId.MIT, - "MIT License" to LicenseId.MIT, - "http://opensource.org/licenses/MIT" to LicenseId.MIT, - "https://opensource.org/licenses/MIT" to LicenseId.MIT, - - // Mozilla Public License 2.0 - // https://github.com/github/choosealicense.com/blob/gh-pages/_licenses/mpl-2.0.txt - "MPL-2.0" to LicenseId.MPL_2, - "Mozilla Public License 2.0" to LicenseId.MPL_2, - "http://www.mozilla.org/media/MPL/2.0/index.txt" to LicenseId.MPL_2, - "https://www.mozilla.org/media/MPL/2.0/index.txt" to LicenseId.MPL_2, - "http://opensource.org/licenses/MPL-2.0" to LicenseId.MPL_2, - "https://opensource.org/licenses/MPL-2.0" to LicenseId.MPL_2, - - // Common Development and Distribution License 1.0 - "CDDL-1.0" to LicenseId.CDDL, - "Common Development and Distribution License 1.0" to LicenseId.CDDL, - "http://opensource.org/licenses/cddl1" to LicenseId.CDDL, - "https://opensource.org/licenses/cddl1" to LicenseId.CDDL -) - @OptIn(ExperimentalStdlibApi::class) fun List.toLicensesMap(): Map> = buildMap> { this@toLicensesMap.forEach { library -> diff --git a/src/main/kotlin/com/cmgapps/license/model/Models.kt b/src/main/kotlin/com/cmgapps/license/model/Models.kt index 6b4f879..8dea78d 100644 --- a/src/main/kotlin/com/cmgapps/license/model/Models.kt +++ b/src/main/kotlin/com/cmgapps/license/model/Models.kt @@ -13,6 +13,7 @@ import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder +import org.apache.commons.csv.CSVFormat import org.apache.maven.artifact.versioning.ComparableVersion @Serializable @@ -38,35 +39,19 @@ data class MavenCoordinates( } } -enum class LicenseId { - APACHE, - CDDL, - BSD_2, - BSD_3, - EPL_2, - GPL_2, - GPL_3, - LGPL_2_1, - LGPL_3, - MIT, - MPL_2, - UNKNOWN; - - val spdxLicenseIdentifier: String? - get() = when (this) { - APACHE -> "Apache-2.0" - BSD_2 -> "BSD-2-Clause" - BSD_3 -> "BSD-3-Clause" - CDDL -> "CDDL-1.0" - UNKNOWN -> null - EPL_2 -> "EPL-2.0" - GPL_2 -> "GPL-2.0-only" - GPL_3 -> "GPL-3.0-only" - LGPL_2_1 -> "LGPL-2.1-only" - LGPL_3 -> "LGPL-3.0-only" - MIT -> "MIT" - MPL_2 -> "MPL-2.0" - } +enum class LicenseId(val spdxLicenseIdentifier: String?) { + APACHE("Apache-2.0"), + BSD_2("BSD-2-Clause"), + BSD_3("BSD-3-Clause"), + CDDL("CDDL-1.0"), + EPL_2("EPL-2.0"), + GPL_2("GPL-2.0-only"), + GPL_3("GPL-3.0-only"), + LGPL_2_1("LGPL-2.1-only"), + LGPL_3("LGPL-3.0-only"), + MIT("MIT"), + MPL_2("MPL-2.0"), + UNKNOWN(null); companion object { @JvmStatic @@ -84,6 +69,19 @@ enum class LicenseId { "MPL-2.0" -> MPL_2 else -> UNKNOWN } + + /** + * Map License name or URL to license id. + * + * Based on "popular and widely-used or with strong communities" found here: https://opensource.org/licenses/category. + * License text from: https://github.com/github/choosealicense.com/blob/gh-pages/_licenses. + */ + internal val map: Map by lazy { + CSVFormat.DEFAULT.parse(this::class.java.getResourceAsStream("/license_map.csv")?.bufferedReader()) + .associate { + it.get(0) to LicenseId.valueOf(it.get(1)) + } + } } } diff --git a/src/main/resources/license_map.csv b/src/main/resources/license_map.csv new file mode 100644 index 0000000..d12a949 --- /dev/null +++ b/src/main/resources/license_map.csv @@ -0,0 +1,69 @@ +Apache-2.0,APACHE +Apache 2.0,APACHE +Apache v2,APACHE +"Apache License, Version 2.0",APACHE +The Apache Software License,APACHE +"The Apache Software License, Version 2.0",APACHE +http://www.apache.org/licenses/LICENSE-2.0.txt,APACHE +https://www.apache.org/licenses/LICENSE-2.0.txt,APACHE +http://opensource.org/licenses/Apache-2.0,APACHE +https://opensource.org/licenses/Apache-2.0,APACHE +http://www.apache.org/licenses/LICENSE-2.0,APACHE +https://www.apache.org/licenses/LICENSE-2.0,APACHE +BSD-2-Clause,BSD_2 +BSD 2-Clause "Simplified" License,BSD_2 +BSD 2-Clause License,BSD_2 +http://opensource.org/licenses/BSD-2-Clause,BSD_2 +https://opensource.org/licenses/BSD-2-Clause,BSD_2 +BSD-3-Clause,BSD_3 +BSD 3-Clause "New" or "Revised" License,BSD_3 +http://opensource.org/licenses/BSD-3-Clause,BSD_3 +https://opensource.org/licenses/BSD-3-Clause,BSD_3 +EPL-2.0,EPL_2 +Eclipse Public License 2.0,EPL_2 +http://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt,EPL_2 +https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt,EPL_2 +http://opensource.org/licenses/EPL-2.0,EPL_2 +https://opensource.org/licenses/EPL-2.0,EPL_2 +GPL-2.0,GPL_2 +GPL-2.0-only,GPL_2 +GNU General Public License v2.0,GPL_2 +http://www.gnu.org/licenses/gpl-2.0.txt,GPL_2 +https://www.gnu.org/licenses/gpl-2.0.txt,GPL_2 +http://opensource.org/licenses/GPL-2.0,GPL_2 +https://opensource.org/licenses/GPL-2.0,GPL_2 +GPL-3.0,GPL_3 +GPL-3.0-only,GPL_3 +GNU General Public License v3.0,GPL_3 +https//www.gnu.org/licenses/gpl-3.0.txt,GPL_3 +https://www.gnu.org/licenses/gpl-3.0.txt,GPL_3 +http://opensource.org/licenses/GPL-3.0,GPL_3 +https://opensource.org/licenses/GPL-3.0,GPL_3 +LGPL-2.1,LGPL_2_1 +LGPL-2.1-only,LGPL_2_1 +GNU Lesser General Public License v2.1,LGPL_2_1 +http://www.gnu.org/licenses/lgpl-2.1.txt,LGPL_2_1 +https://www.gnu.org/licenses/lgpl-2.1.txt,LGPL_2_1 +http://opensource.org/licenses/LGPL-2.1,LGPL_2_1 +https://opensource.org/licenses/LGPL-2.1,LGPL_2_1 +LGPL-3.0,LGPL_3 +LGPL-3.0-only,LGPL_3 +GNU Lesser General Public License v3.0,LGPL_3 +http://www.gnu.org/licenses/lgpl-3.0.txt,LGPL_3 +https://www.gnu.org/licenses/lgpl-3.0.txt,LGPL_3 +http://opensource.org/licenses/LGPL-3.0,LGPL_3 +https://opensource.org/licenses/LGPL-3.0,LGPL_3 +MIT,MIT +MIT License,MIT +http://opensource.org/licenses/MIT,MIT +https://opensource.org/licenses/MIT,MIT +MPL-2.0,MPL_2 +Mozilla Public License 2.0,MPL_2 +http://www.mozilla.org/media/MPL/2.0/index.txt,MPL_2 +https://www.mozilla.org/media/MPL/2.0/index.txt,MPL_2 +http://opensource.org/licenses/MPL-2.0,MPL_2 +https://opensource.org/licenses/MPL-2.0,MPL_2 +CDDL-1.0,CDDL +Common Development and Distribution License 1.0,CDDL +http://opensource.org/licenses/cddl1,CDDL +https://opensource.org/licenses/cddl1,CDDL diff --git a/src/main/xsd/licenses.xsd b/src/main/xsd/licenses.xsd index db13a74..18e43a3 100644 --- a/src/main/xsd/licenses.xsd +++ b/src/main/xsd/licenses.xsd @@ -8,7 +8,6 @@ = Stream.of( + Arguments.of(LicenseId.APACHE, 12), + Arguments.of(LicenseId.BSD_2, 5), + Arguments.of(LicenseId.BSD_3, 4), + Arguments.of(LicenseId.EPL_2, 6), + Arguments.of(LicenseId.GPL_2, 7), + Arguments.of(LicenseId.GPL_3, 7), + Arguments.of(LicenseId.LGPL_2_1, 7), + Arguments.of(LicenseId.LGPL_3, 7), + Arguments.of(LicenseId.MIT, 4), + Arguments.of(LicenseId.MPL_2, 6), + Arguments.of(LicenseId.CDDL, 4), + ) + } } diff --git a/src/test/kotlin/com/cmgapps/license/reporter/CsvReportShould.kt b/src/test/kotlin/com/cmgapps/license/reporter/CsvReportShould.kt index ab025a4..cc21a10 100644 --- a/src/test/kotlin/com/cmgapps/license/reporter/CsvReportShould.kt +++ b/src/test/kotlin/com/cmgapps/license/reporter/CsvReportShould.kt @@ -6,11 +6,11 @@ package com.cmgapps.license.reporter -import com.cmgapps.license.helper.testLibraries import com.cmgapps.license.model.Library import com.cmgapps.license.model.License import com.cmgapps.license.model.LicenseId import com.cmgapps.license.model.MavenCoordinates +import com.cmgapps.license.util.testLibraries import org.apache.maven.artifact.versioning.ComparableVersion import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.`is` diff --git a/src/test/kotlin/com/cmgapps/license/reporter/HtmlReportShould.kt b/src/test/kotlin/com/cmgapps/license/reporter/HtmlReportShould.kt index 89ee478..8fc20c2 100644 --- a/src/test/kotlin/com/cmgapps/license/reporter/HtmlReportShould.kt +++ b/src/test/kotlin/com/cmgapps/license/reporter/HtmlReportShould.kt @@ -6,11 +6,11 @@ package com.cmgapps.license.reporter -import com.cmgapps.license.helper.testLibraries import com.cmgapps.license.model.License import com.cmgapps.license.model.LicenseId import com.cmgapps.license.model.MavenCoordinates import com.cmgapps.license.util.getFileContent +import com.cmgapps.license.util.testLibraries import org.apache.maven.artifact.versioning.ComparableVersion import org.gradle.api.logging.Logger import org.gradle.api.logging.Logging diff --git a/src/test/kotlin/com/cmgapps/license/reporter/JsonReportShould.kt b/src/test/kotlin/com/cmgapps/license/reporter/JsonReportShould.kt index daaf40e..df51766 100644 --- a/src/test/kotlin/com/cmgapps/license/reporter/JsonReportShould.kt +++ b/src/test/kotlin/com/cmgapps/license/reporter/JsonReportShould.kt @@ -6,7 +6,7 @@ package com.cmgapps.license.reporter -import com.cmgapps.license.helper.testLibraries +import com.cmgapps.license.util.testLibraries import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.`is` import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/com/cmgapps/license/reporter/MarkdownReportShould.kt b/src/test/kotlin/com/cmgapps/license/reporter/MarkdownReportShould.kt index 7c4d054..23504b8 100644 --- a/src/test/kotlin/com/cmgapps/license/reporter/MarkdownReportShould.kt +++ b/src/test/kotlin/com/cmgapps/license/reporter/MarkdownReportShould.kt @@ -6,12 +6,12 @@ package com.cmgapps.license.reporter -import com.cmgapps.license.helper.testLibraries import com.cmgapps.license.model.Library import com.cmgapps.license.model.License import com.cmgapps.license.model.LicenseId import com.cmgapps.license.model.MavenCoordinates import com.cmgapps.license.util.getFileContent +import com.cmgapps.license.util.testLibraries import org.apache.maven.artifact.versioning.ComparableVersion import org.gradle.api.logging.Logger import org.gradle.api.logging.Logging diff --git a/src/test/kotlin/com/cmgapps/license/reporter/TextReportShould.kt b/src/test/kotlin/com/cmgapps/license/reporter/TextReportShould.kt index 5563db4..a73b924 100644 --- a/src/test/kotlin/com/cmgapps/license/reporter/TextReportShould.kt +++ b/src/test/kotlin/com/cmgapps/license/reporter/TextReportShould.kt @@ -6,9 +6,9 @@ package com.cmgapps.license.reporter -import com.cmgapps.license.helper.testLibraries import com.cmgapps.license.model.Library import com.cmgapps.license.model.MavenCoordinates +import com.cmgapps.license.util.testLibraries import org.apache.maven.artifact.versioning.ComparableVersion import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.`is` diff --git a/src/test/kotlin/com/cmgapps/license/reporter/XmlReportShould.kt b/src/test/kotlin/com/cmgapps/license/reporter/XmlReportShould.kt index d4b38da..8bb7a8d 100644 --- a/src/test/kotlin/com/cmgapps/license/reporter/XmlReportShould.kt +++ b/src/test/kotlin/com/cmgapps/license/reporter/XmlReportShould.kt @@ -6,7 +6,7 @@ package com.cmgapps.license.reporter -import com.cmgapps.license.helper.testLibraries +import com.cmgapps.license.util.testLibraries import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.`is` import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/com/cmgapps/license/util/LibrariesHelper.kt b/src/test/kotlin/com/cmgapps/license/util/LibrariesHelper.kt index 9206b9f..87aabac 100644 --- a/src/test/kotlin/com/cmgapps/license/util/LibrariesHelper.kt +++ b/src/test/kotlin/com/cmgapps/license/util/LibrariesHelper.kt @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -package com.cmgapps.license.helper +package com.cmgapps.license.util import com.cmgapps.license.model.Library import com.cmgapps.license.model.License