Skip to content

Commit 83e5bed

Browse files
committed
refactor(scanoss): Replace direct API calls with SCANOSS SDK
Replace custom direct API calls to SCANOSS with the official Java SDK. This change improves maintainability by leveraging the SDK's functionality instead of maintaining custom implementation for API interactions. Signed-off-by: Agustin Isasmendi <[email protected]>
1 parent 9d6a7e8 commit 83e5bed

File tree

4 files changed

+12
-101
lines changed

4 files changed

+12
-101
lines changed

plugins/scanners/scanoss/src/main/kotlin/ScanOss.kt

Lines changed: 11 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,20 @@
1919

2020
package org.ossreviewtoolkit.plugins.scanners.scanoss
2121

22-
import com.scanoss.Winnowing
23-
import com.scanoss.dto.ScanFileResult
24-
import com.scanoss.rest.ScanApi
22+
import com.scanoss.Scanner
2523
import com.scanoss.utils.JsonUtils
2624
import com.scanoss.utils.PackageDetails
2725

2826
import java.io.File
2927
import java.time.Instant
30-
import java.util.UUID
31-
32-
import org.apache.logging.log4j.kotlin.logger
3328

3429
import org.ossreviewtoolkit.model.ScanSummary
3530
import org.ossreviewtoolkit.plugins.api.OrtPlugin
3631
import org.ossreviewtoolkit.plugins.api.PluginDescriptor
3732
import org.ossreviewtoolkit.scanner.PathScannerWrapper
3833
import org.ossreviewtoolkit.scanner.ScanContext
3934
import org.ossreviewtoolkit.scanner.ScannerMatcher
40-
import org.ossreviewtoolkit.scanner.ScannerMatcherConfig
4135
import org.ossreviewtoolkit.scanner.ScannerWrapperFactory
42-
import org.ossreviewtoolkit.utils.common.VCS_DIRECTORIES
4336

4437
@OrtPlugin(
4538
id = "SCANOSS",
@@ -49,13 +42,8 @@ import org.ossreviewtoolkit.utils.common.VCS_DIRECTORIES
4942
)
5043
class ScanOss(
5144
override val descriptor: PluginDescriptor = ScanOssFactory.descriptor,
52-
config: ScanOssConfig
45+
private var config: ScanOssConfig
5346
) : PathScannerWrapper {
54-
private val service = ScanApi.builder()
55-
// As there is only a single endpoint, the SCANOSS API client expects the path to be part of the API URL.
56-
.url(config.apiUrl.removeSuffix("/") + "/scan/direct")
57-
.apiKey(config.apiKey.value)
58-
.build()
5947

6048
override val version: String by lazy {
6149
// TODO: Find out the best / cheapest way to query the SCANOSS server for its version.
@@ -64,73 +52,27 @@ class ScanOss(
6452

6553
override val configuration = ""
6654

67-
override val matcher by lazy {
68-
ScannerMatcher.create(
69-
details,
70-
ScannerMatcherConfig(
71-
config.regScannerName,
72-
config.minVersion,
73-
config.maxVersion,
74-
configuration
75-
)
76-
)
77-
}
55+
override val matcher: ScannerMatcher? = null
7856

7957
override val readFromStorage = config.readFromStorage
8058

8159
override val writeToStorage = config.writeToStorage
8260

83-
/**
84-
* The name of the file corresponding to the fingerprints can be sent to SCANOSS for more precise matches.
85-
* However, for anonymity, a unique identifier should be generated and used instead. This property holds the
86-
* mapping between the file paths and the unique identifiers. When receiving the response, the UUID will be
87-
* replaced by the actual file path.
88-
*
89-
* TODO: This behavior should be driven by a configuration parameter enabled by default.
90-
*/
91-
private val fileNamesAnonymizationMapping = mutableMapOf<UUID, String>()
92-
9361
override fun scanPath(path: File, context: ScanContext): ScanSummary {
9462
val startTime = Instant.now()
9563

96-
val wfpString = buildString {
97-
path.walk()
98-
.onEnter { it.name !in VCS_DIRECTORIES }
99-
.filterNot { it.isDirectory }
100-
.forEach {
101-
logger.info { "Computing fingerprint for file ${it.absolutePath}..." }
102-
append(createWfpForFile(it))
103-
}
104-
}
105-
106-
val result = service.scan(
107-
wfpString,
108-
context.labels["scanOssContext"],
109-
context.labels["scanOssId"]?.toIntOrNull() ?: Thread.currentThread().threadId().toInt()
110-
)
111-
112-
// Replace the anonymized UUIDs by their file paths.
113-
val results = JsonUtils.toScanFileResultsFromObject(JsonUtils.toJsonObject(result)).map {
114-
val uuid = UUID.fromString(it.filePath)
64+
val scanoss = Scanner.builder()
65+
.url(config.apiUrl.removeSuffix("/") + "/scan/direct")
66+
.apiKey(config.apiKey.value)
67+
.build()
11568

116-
val fileName = fileNamesAnonymizationMapping[uuid] ?: throw IllegalArgumentException(
117-
"The ${descriptor.id} server returned UUID '$uuid' which is not present in the mapping."
118-
)
119-
120-
ScanFileResult(fileName, it.fileDetails)
69+
val rawResults: List<String> = when {
70+
path.isFile -> listOf(scanoss.scanFile(path.absolutePath))
71+
else -> scanoss.scanFolder(path.absolutePath)
12172
}
12273

74+
val results = JsonUtils.toScanFileResults(rawResults)
12375
val endTime = Instant.now()
12476
return generateSummary(startTime, endTime, results)
12577
}
126-
127-
internal fun generateRandomUUID() = UUID.randomUUID()
128-
129-
internal fun createWfpForFile(file: File): String {
130-
generateRandomUUID().let { uuid ->
131-
// TODO: Let's keep the original file extension to give SCANOSS some hint about the mime type.
132-
fileNamesAnonymizationMapping[uuid] = file.path
133-
return Winnowing.builder().build().wfpForFile(file.path, uuid.toString())
134-
}
135-
}
13678
}

plugins/scanners/scanoss/src/test/assets/scanMulti/mappings/scanoss-multi-response.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
},
1111
"response" : {
1212
"status" : 200,
13-
"body" : "{ \"c198b884-f6cf-496f-95eb-0e7968dd2ec6\": [ { \"id\": \"snippet\", \"status\": \"pending\", \"lines\": \"1-240\", \"oss_lines\": \"128-367\", \"matched\": \"99%\", \"purl\": [ \"pkg:github/scanoss/ort\" ], \"vendor\": \"scanoss\", \"component\": \"ort\", \"version\": \"e654028\", \"latest\": \"b12f8ee\", \"url\": \"https://github.com/scanoss/ort\", \"release_date\": \"2021-03-18\", \"file\": \"utils/src/main/kotlin/ArchiveUtils.kt\", \"url_hash\": \"37faa38a820322fa93bf7a8fa8290bb8\", \"file_hash\": \"871fb0c5188c2f620d9b997e225b0095\", \"source_hash\": \"2e91edbe430c4eb195a977d326d6d6c0\", \"file_url\": \"https://osskb.org/api/file_contents/871fb0c5188c2f620d9b997e225b0095\", \"licenses\": [ { \"name\": \"Apache-2.0\", \"patent_hints\": \"yes\", \"copyleft\": \"no\", \"checklist_url\": \"https://www.osadl.org/fileadmin/checklists/unreflicenses/Apache-2.0.txt\", \"osadl_updated\": \"2022-03-17 13:38\", \"source\": \"file_spdx_tag\" }, { \"name\": \"Apache-2.0\", \"patent_hints\": \"yes\", \"copyleft\": \"no\", \"checklist_url\": \"https://www.osadl.org/fileadmin/checklists/unreflicenses/Apache-2.0.txt\", \"osadl_updated\": \"2022-03-17 13:38\", \"source\": \"scancode\" } ], \"server\": { \"version\": \"4.4.2\", \"kb_version\": { \"monthly\": \"22.02\", \"daily\": \"22.03.25\" } } } ], \"5530105e-0752-4750-9c07-4e4604b879a5\": [ { \"id\": \"file\", \"status\": \"pending\", \"lines\": \"all\", \"oss_lines\": \"all\", \"matched\": \"100%\", \"purl\": [ \"pkg:github/scanoss/ort\" ], \"vendor\": \"scanoss\", \"component\": \"ort\", \"version\": \"e654028\", \"latest\": \"b12f8ee\", \"url\": \"https://github.com/scanoss/ort\", \"release_date\": \"2021-03-18\", \"file\": \"scanner/src/main/kotlin/ScannerFactory.kt\", \"url_hash\": \"37faa38a820322fa93bf7a8fa8290bb8\", \"file_hash\": \"5c8ab9be40df937e46c53509481107cd\", \"source_hash\": \"5c8ab9be40df937e46c53509481107cd\", \"file_url\": \"https://osskb.org/api/file_contents/5c8ab9be40df937e46c53509481107cd\", \"licenses\": [ { \"name\": \"Apache-2.0\", \"patent_hints\": \"yes\", \"copyleft\": \"no\", \"checklist_url\": \"https://www.osadl.org/fileadmin/checklists/unreflicenses/Apache-2.0.txt\", \"osadl_updated\": \"2022-03-17 13:38\", \"source\": \"file_spdx_tag\" }, { \"name\": \"Apache-2.0\", \"patent_hints\": \"yes\", \"copyleft\": \"no\", \"checklist_url\": \"https://www.osadl.org/fileadmin/checklists/unreflicenses/Apache-2.0.txt\", \"osadl_updated\": \"2022-03-17 13:38\", \"source\": \"scancode\" } ], \"server\": { \"version\": \"4.4.2\", \"kb_version\": { \"monthly\": \"22.02\", \"daily\": \"22.03.25\" } } } ]}",
13+
"body" : "{ \"utils/src/main/kotlin/ArchiveUtils.kt\": [ { \"id\": \"snippet\", \"status\": \"pending\", \"lines\": \"1-240\", \"oss_lines\": \"128-367\", \"matched\": \"99%\", \"purl\": [ \"pkg:github/scanoss/ort\" ], \"vendor\": \"scanoss\", \"component\": \"ort\", \"version\": \"e654028\", \"latest\": \"b12f8ee\", \"url\": \"https://github.com/scanoss/ort\", \"release_date\": \"2021-03-18\", \"file\": \"utils/src/main/kotlin/ArchiveUtils.kt\", \"url_hash\": \"37faa38a820322fa93bf7a8fa8290bb8\", \"file_hash\": \"871fb0c5188c2f620d9b997e225b0095\", \"source_hash\": \"2e91edbe430c4eb195a977d326d6d6c0\", \"file_url\": \"https://osskb.org/api/file_contents/871fb0c5188c2f620d9b997e225b0095\", \"licenses\": [ { \"name\": \"Apache-2.0\", \"patent_hints\": \"yes\", \"copyleft\": \"no\", \"checklist_url\": \"https://www.osadl.org/fileadmin/checklists/unreflicenses/Apache-2.0.txt\", \"osadl_updated\": \"2022-03-17 13:38\", \"source\": \"file_spdx_tag\" }, { \"name\": \"Apache-2.0\", \"patent_hints\": \"yes\", \"copyleft\": \"no\", \"checklist_url\": \"https://www.osadl.org/fileadmin/checklists/unreflicenses/Apache-2.0.txt\", \"osadl_updated\": \"2022-03-17 13:38\", \"source\": \"scancode\" } ], \"server\": { \"version\": \"4.4.2\", \"kb_version\": { \"monthly\": \"22.02\", \"daily\": \"22.03.25\" } } } ], \"5530105e-0752-4750-9c07-4e4604b879a5\": [ { \"id\": \"file\", \"status\": \"pending\", \"lines\": \"all\", \"oss_lines\": \"all\", \"matched\": \"100%\", \"purl\": [ \"pkg:github/scanoss/ort\" ], \"vendor\": \"scanoss\", \"component\": \"ort\", \"version\": \"e654028\", \"latest\": \"b12f8ee\", \"url\": \"https://github.com/scanoss/ort\", \"release_date\": \"2021-03-18\", \"file\": \"scanner/src/main/kotlin/ScannerFactory.kt\", \"url_hash\": \"37faa38a820322fa93bf7a8fa8290bb8\", \"file_hash\": \"5c8ab9be40df937e46c53509481107cd\", \"source_hash\": \"5c8ab9be40df937e46c53509481107cd\", \"file_url\": \"https://osskb.org/api/file_contents/5c8ab9be40df937e46c53509481107cd\", \"licenses\": [ { \"name\": \"Apache-2.0\", \"patent_hints\": \"yes\", \"copyleft\": \"no\", \"checklist_url\": \"https://www.osadl.org/fileadmin/checklists/unreflicenses/Apache-2.0.txt\", \"osadl_updated\": \"2022-03-17 13:38\", \"source\": \"file_spdx_tag\" }, { \"name\": \"Apache-2.0\", \"patent_hints\": \"yes\", \"copyleft\": \"no\", \"checklist_url\": \"https://www.osadl.org/fileadmin/checklists/unreflicenses/Apache-2.0.txt\", \"osadl_updated\": \"2022-03-17 13:38\", \"source\": \"scancode\" } ], \"server\": { \"version\": \"4.4.2\", \"kb_version\": { \"monthly\": \"22.02\", \"daily\": \"22.03.25\" } } } ]}",
1414
"headers" : {
1515
"Server" : "nginx/1.14.2",
1616
"Date" : "Wed, 16 Mar 2022 13:07:04 GMT",

plugins/scanners/scanoss/src/test/kotlin/ScanOssScannerDirectoryTest.kt

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,9 @@ import io.kotest.matchers.collections.containExactlyInAnyOrder
2727
import io.kotest.matchers.collections.shouldContainExactly
2828
import io.kotest.matchers.should
2929

30-
import io.mockk.every
3130
import io.mockk.spyk
32-
import io.mockk.verify
3331

3432
import java.io.File
35-
import java.util.UUID
3633

3734
import org.ossreviewtoolkit.model.LicenseFinding
3835
import org.ossreviewtoolkit.model.PackageType
@@ -74,25 +71,11 @@ class ScanOssScannerDirectoryTest : StringSpec({
7471
}
7572

7673
"The scanner should scan a directory" {
77-
// Manipulate the UUID generation to have the same IDs as in the response.
78-
every {
79-
scanner.generateRandomUUID()
80-
} answers {
81-
UUID.fromString("5530105e-0752-4750-9c07-4e4604b879a5")
82-
} andThenAnswer {
83-
UUID.fromString("c198b884-f6cf-496f-95eb-0e7968dd2ec6")
84-
}
85-
8674
val summary = scanner.scanPath(
8775
TEST_DIRECTORY_TO_SCAN,
8876
ScanContext(labels = emptyMap(), packageType = PackageType.PACKAGE)
8977
)
9078

91-
verify(exactly = 1) {
92-
scanner.createWfpForFile(TEST_DIRECTORY_TO_SCAN.resolve("ArchiveUtils.kt"))
93-
scanner.createWfpForFile(TEST_DIRECTORY_TO_SCAN.resolve("ScannerFactory.kt"))
94-
}
95-
9679
with(summary) {
9780
licenseFindings should containExactlyInAnyOrder(
9881
LicenseFinding(

plugins/scanners/scanoss/src/test/kotlin/ScanOssScannerFileTest.kt

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,9 @@ import io.kotest.core.spec.style.StringSpec
2626
import io.kotest.matchers.collections.containExactly
2727
import io.kotest.matchers.should
2828

29-
import io.mockk.every
3029
import io.mockk.spyk
31-
import io.mockk.verify
3230

3331
import java.io.File
34-
import java.util.UUID
3532

3633
import org.ossreviewtoolkit.model.LicenseFinding
3734
import org.ossreviewtoolkit.model.PackageType
@@ -67,22 +64,11 @@ class ScanOssScannerFileTest : StringSpec({
6764
}
6865

6966
"The scanner should scan a single file" {
70-
// Manipulate the UUID generation to have the same IDs as in the response.
71-
every {
72-
scanner.generateRandomUUID()
73-
} answers {
74-
UUID.fromString("bf5401e9-03b3-4c91-906c-cadb90487b8c")
75-
}
76-
7767
val summary = scanner.scanPath(
7868
TEST_FILE_TO_SCAN,
7969
ScanContext(labels = emptyMap(), packageType = PackageType.PACKAGE)
8070
)
8171

82-
verify(exactly = 1) {
83-
scanner.createWfpForFile(TEST_FILE_TO_SCAN)
84-
}
85-
8672
with(summary) {
8773
licenseFindings should containExactly(
8874
LicenseFinding(

0 commit comments

Comments
 (0)