From 0f67acd8d5c39c70e66eadcb312648f18dadbcaa Mon Sep 17 00:00:00 2001 From: Rainer Bieniek Date: Wed, 4 May 2022 17:52:52 +0200 Subject: [PATCH] Introduce ORT result scanner infrastructre As explained in the issue https://github.com/oss-review-toolkit/ort/issues/5324, we need a scanner with the capability to access and autonomously process the full ORT result into a scan result structure. This pull request gives an insight on how we solved this requirement using the current ORT infrastructure. This has to be seen as an example and a base for further discussion on the ORT developer community. Signed-off-by: Rainer Bieniek --- scanner/src/main/kotlin/OrtResultScanner.kt | 55 +++++++++++++++++++++ scanner/src/main/kotlin/Scanner.kt | 52 +++++++++++-------- 2 files changed, 87 insertions(+), 20 deletions(-) create mode 100644 scanner/src/main/kotlin/OrtResultScanner.kt diff --git a/scanner/src/main/kotlin/OrtResultScanner.kt b/scanner/src/main/kotlin/OrtResultScanner.kt new file mode 100644 index 000000000000..507ab6357882 --- /dev/null +++ b/scanner/src/main/kotlin/OrtResultScanner.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2021 Porsche AG + * + * 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 + * + * https://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 + * License-Filename: LICENSE + */ +package org.ossreviewtoolkit.scanner + +import org.ossreviewtoolkit.model.OrtResult +import org.ossreviewtoolkit.model.Package +import org.ossreviewtoolkit.model.ScanResult +import org.ossreviewtoolkit.model.config.DownloaderConfiguration +import org.ossreviewtoolkit.model.config.ScannerConfiguration + +/** + * A [Scanner] that operates on a complete [OrtResult] + */ +abstract class OrtResultScanner( + scannerName: String, + scannerConfig: ScannerConfiguration, + downloaderConfig: DownloaderConfiguration +) : Scanner(scannerName, scannerConfig, downloaderConfig) { + + /** + * This scanner operates on the level of a complete [OrtResult]. + * + * Using it for package scanning is neither wanted nor supported and must be considered as an error. + */ + final override suspend fun scanPackages( + packages: Set, + labels: Map + ): Map> = + throw NotImplementedError("Not implemented on purpose") + + /** + * Process a complete [OrtResult] and manage any scanning activities on projects and packages + * autonomous without any orchestration from ORT + */ + abstract suspend fun scanOrtResult( + ortResult: OrtResult, + labels: Map + ): Map> +} diff --git a/scanner/src/main/kotlin/Scanner.kt b/scanner/src/main/kotlin/Scanner.kt index ea404380152a..af628dc1f466 100644 --- a/scanner/src/main/kotlin/Scanner.kt +++ b/scanner/src/main/kotlin/Scanner.kt @@ -102,33 +102,45 @@ fun scanOrtResult( .filter { it.pkg.id !in projectPackageIds } .map { it.pkg } - val scanResults = runBlocking { - val deferredProjectScan = async { - if (projectScanner == null) emptyMap() - else { - // Scan the projects from the ORT result. - val filteredProjectPackages = removeConcludedPackages(projectPackages, projectScanner) - - if (filteredProjectPackages.isEmpty()) emptyMap() - else projectScanner.scanPackages(filteredProjectPackages, ortResult.labels).mapKeys { it.key.id } + val scanResults = if (packageScanner is OrtResultScanner) { + runBlocking { + val deferredScanResults = async { + packageScanner.scanOrtResult(ortResult, ortResult.labels).mapKeys { it.key.id } } + + val scanResult = deferredScanResults.await() + + scanResult } + } else { + runBlocking { + val deferredProjectScan = async { + if (projectScanner == null) emptyMap() + else { + // Scan the projects from the ORT result. + val filteredProjectPackages = removeConcludedPackages(projectPackages, projectScanner) + + if (filteredProjectPackages.isEmpty()) emptyMap() + else projectScanner.scanPackages(filteredProjectPackages, ortResult.labels).mapKeys { it.key.id } + } + } - val deferredPackageScan = async { - if (packageScanner == null) emptyMap() - else { - // Scan the packages from the ORT result. - val filteredPackages = removeConcludedPackages(packages.toSet(), packageScanner) + val deferredPackageScan = async { + if (packageScanner == null) emptyMap() + else { + // Scan the packages from the ORT result. + val filteredPackages = removeConcludedPackages(packages.toSet(), packageScanner) - if (filteredPackages.isEmpty()) emptyMap() - else packageScanner.scanPackages(filteredPackages, ortResult.labels).mapKeys { it.key.id } + if (filteredPackages.isEmpty()) emptyMap() + else packageScanner.scanPackages(filteredPackages, ortResult.labels).mapKeys { it.key.id } + } } - } - val projectResults = deferredProjectScan.await() - val packageResults = deferredPackageScan.await() + val projectResults = deferredProjectScan.await() + val packageResults = deferredPackageScan.await() - projectResults + packageResults + projectResults + packageResults + } }.toSortedMap() // Add scan results from de-duplicated project packages to result.