Skip to content

Commit b5ca400

Browse files
committed
Add SpdxLicense.fromUri, extract OsgiBundleLicenseParser and add tests
1 parent 15946a9 commit b5ca400

File tree

4 files changed

+155
-36
lines changed

4 files changed

+155
-36
lines changed

buildSrc/subprojects/license-texts/src/main/kotlin/com/github/vlsi/gradle/license/EnumGeneratorTask.kt

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,14 +171,26 @@ open class EnumGeneratorTask @Inject constructor(objectFactory: ObjectFactory) :
171171
)
172172
.addFunction(
173173
FunSpec.builder("fromUri")
174-
.addParameter("uri", String::class)
175-
.addStatement("return uriToInstance.getValue(URI(uri.replaceFirst(\"http://\", \"https://\")))")
174+
.addParameter("uri", URI::class)
175+
.addStatement(
176+
"return fromUriOrNull(uri) ?: throw %T(%P)",
177+
NoSuchElementException::class,
178+
"No license found for given URI: \$uri"
179+
)
176180
.build()
177181
)
178182
.addFunction(
179183
FunSpec.builder("fromUriOrNull")
180-
.addParameter("uri", String::class)
181-
.addStatement("return uriToInstance[URI(uri.replaceFirst(\"http://\", \"https://\"))]")
184+
.addParameter("uri", URI::class)
185+
.addStatement("return uriToInstance[uri.toHttps()]")
186+
.build()
187+
)
188+
.addFunction(
189+
FunSpec.builder("toHttps")
190+
.addModifiers(KModifier.PRIVATE)
191+
.receiver(URI::class)
192+
.returns(URI::class)
193+
.addStatement("return if (!toString().startsWith(\"http://\")) this else URI(toString().replaceFirst(\"http:\", \"https:\"))")
182194
.build()
183195
)
184196
.build()

plugins/license-gather-plugin/src/main/kotlin/com/github/vlsi/gradle/license/GatherLicenseTask.kt

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import com.github.vlsi.gradle.license.api.JustLicense
2222
import com.github.vlsi.gradle.license.api.License
2323
import com.github.vlsi.gradle.license.api.LicenseExpression
2424
import com.github.vlsi.gradle.license.api.LicenseExpressionParser
25+
import com.github.vlsi.gradle.license.api.OsgiBundleLicenseParser
2526
import com.github.vlsi.gradle.license.api.ParseException
2627
import com.github.vlsi.gradle.license.api.SpdxLicense
2728
import com.github.vlsi.gradle.license.api.asExpression
@@ -472,6 +473,9 @@ open class GatherLicenseTask @Inject constructor(
472473
detectedLicenses: MutableMap<ComponentIdentifier, LicenseInfo>,
473474
licenseExpressionParser: LicenseExpressionParser
474475
) {
476+
val bundleLicenseParser = OsgiBundleLicenseParser(licenseExpressionParser) {
477+
SpdxLicense.fromUriOrNull(it)?.asExpression()
478+
}
475479
for (e in detectedLicenses) {
476480
if (e.value.license != null) {
477481
continue
@@ -502,38 +506,7 @@ open class GatherLicenseTask @Inject constructor(
502506
JarFile(file).use { jar ->
503507
val bundleLicense = jar.manifest.mainAttributes.getValue("Bundle-License")
504508
?: return@use
505-
if (bundleLicense.contains(',')) {
506-
logger.info(
507-
"Ignoring Bundle-License '{}' in file {} since it contains multiple license references",
508-
bundleLicense,
509-
file
510-
)
511-
return@use
512-
}
513-
514-
val license = if (bundleLicense.startsWith("http")) {
515-
// Infer license from the URI
516-
SpdxLicense.fromUriOrNull(bundleLicense)?.asExpression()
517-
} else {
518-
// Infer license from "SPDX-Expression; licenseURI"
519-
// We ignore URI as the expression should be more important
520-
bundleLicense.substringBefore(";")
521-
.takeUnless { it.startsWith("http") }
522-
?.let {
523-
try {
524-
licenseExpressionParser.parse(it)
525-
} catch (e: ParseException) {
526-
logger.info(
527-
"Unable to parse Bundle-License value '{}' from file {}",
528-
bundleLicense,
529-
file,
530-
e
531-
)
532-
null
533-
}
534-
}
535-
}
536-
if (license != null) {
509+
bundleLicenseParser.parseOrNull(bundleLicense, file)?.let { license ->
537510
logger.debug("Detected license for ${e.key}: $license")
538511
e.setValue(e.value.copy(license = license))
539512
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2019 Vladimir Sitnikov <[email protected]>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package com.github.vlsi.gradle.license.api
19+
20+
import org.slf4j.LoggerFactory
21+
import java.net.URI
22+
import java.net.URISyntaxException
23+
24+
class OsgiBundleLicenseParser(
25+
private val licenseExpressionParser: LicenseExpressionParser,
26+
private val lookupLicenseByUri: (URI) -> LicenseExpression?
27+
) {
28+
private val logger = LoggerFactory.getLogger(OsgiBundleLicenseParser::class.java)
29+
30+
fun parseOrNull(bundleLicense: String, context: Any): LicenseExpression? {
31+
return if (bundleLicense.contains(',')) {
32+
logger.info(
33+
"Ignoring Bundle-License '{}' in {} since it contains multiple license references",
34+
bundleLicense,
35+
context
36+
)
37+
null
38+
} else if (bundleLicense.startsWith("http")) {
39+
// Infer license from the URI
40+
val uri = try {
41+
URI(bundleLicense)
42+
} catch (e: URISyntaxException) {
43+
logger.info(
44+
"Invalid URI for license in Bundle-License value '{}' in {}",
45+
bundleLicense,
46+
context,
47+
e
48+
)
49+
return null
50+
}
51+
lookupLicenseByUri(uri)
52+
} else {
53+
// Infer license from "SPDX-Expression; licenseURI"
54+
// We ignore URI as the expression should be more important
55+
bundleLicense.substringBefore(";").let {
56+
try {
57+
licenseExpressionParser.parse(it)
58+
} catch (e: ParseException) {
59+
logger.info(
60+
"Unable to parse Bundle-License value '{}' in {}",
61+
bundleLicense,
62+
context,
63+
e
64+
)
65+
null
66+
}
67+
}
68+
}
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2019 Vladimir Sitnikov <[email protected]>
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package com.github.vlsi.gradle.license
19+
20+
import com.github.vlsi.gradle.license.api.LicenseExpressionParser
21+
import com.github.vlsi.gradle.license.api.OsgiBundleLicenseParser
22+
import com.github.vlsi.gradle.license.api.SpdxLicense
23+
import com.github.vlsi.gradle.license.api.asExpression
24+
import org.junit.jupiter.api.Assertions.assertEquals
25+
import org.junit.jupiter.api.Assertions.assertNull
26+
import org.junit.jupiter.params.ParameterizedTest
27+
import org.junit.jupiter.params.provider.CsvSource
28+
29+
class OsgiBundleLicenseParserTest {
30+
@ParameterizedTest
31+
@CsvSource(
32+
"license from https uri^Apache-2.0^https://www.apache.org/licenses/LICENSE-2.0",
33+
"license from http uri^Apache-2.0^http://www.apache.org/licenses/LICENSE-2.0",
34+
"license from https uri^Apache-1.0^https://www.apache.org/licenses/LICENSE-1.0",
35+
"license from SPDX^Apache-2.0^Apache-2.0;https://www.apache.org/licenses/LICENSE-1.0",
36+
"SPDX expression^Apache-1.0 OR Apache-2.0^Apache-2.0 OR Apache-1.0;https://www.apache.org/licenses/LICENSE-1.0",
37+
delimiter = '^'
38+
)
39+
fun success(comment: String, expected: String, input: String) {
40+
val parser = OsgiBundleLicenseParser(LicenseExpressionParser()) {
41+
SpdxLicense.fromUriOrNull(it)?.asExpression()
42+
}
43+
assertEquals(expected, parser.parseOrNull(input, "test input").toString()) {
44+
"$comment, input: $input"
45+
}
46+
}
47+
48+
@ParameterizedTest
49+
@CsvSource(
50+
"unknown uri^https://www.apache.org/licenses/LICENSE-1.2",
51+
"invalid expression^Apache OR;http://www.apache.org/licenses/LICENSE-2.0",
52+
"multiple licenses^license1,license2",
53+
"multiple licenses^Apache-2.0;https://www.apache.org/licenses/LICENSE-2.0,Apache_1.0;https://www.apache.org/licenses/LICENSE-1.0",
54+
delimiter = '^'
55+
)
56+
fun fail(comment: String, input: String) {
57+
val parser = OsgiBundleLicenseParser(LicenseExpressionParser()) {
58+
SpdxLicense.fromUriOrNull(it)?.asExpression()
59+
}
60+
assertNull(parser.parseOrNull(input, "test input")) {
61+
"$comment should cause OsgiBundleLicenseParser.parse failure, input: $input"
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)