/* Ċ Ġ* ĠCopyright Ġ( C ) Ġ 2 0 1 7 - 2 0 1 9 ĠHERE ĠEurope ĠB . V . Ċ Ġ* Ċ Ġ* Ġ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 Ċ Ġ* ĠLicense - Filename : ĠLICENSE Ċ Ġ*/ Ċ Ċ package Ġcom . here . ort . scanner Ċ Ċ import Ġch . fr ank el . slf 4 k .* Ċ Ċ import Ġcom . here . ort . downloader . Downloader Ċ import Ġcom . here . ort . model . Environment Ċ import Ġcom . here . ort . model . Or t Result Ċ import Ġcom . here . ort . model . Package Ċ import Ġcom . here . ort . model . Project Ċ import Ġcom . here . ort . model . Project Scan Scopes Ċ import Ġcom . here . ort . model . Scan Record Ċ import Ġcom . here . ort . model . Scan Result Ċ import Ġcom . here . ort . model . Scan Result Container Ċ import Ġcom . here . ort . model . Scanner Run Ċ import Ġcom . here . ort . model . config . Scanner Configuration Ċ import Ġcom . here . ort . model . readValue Ċ import Ġcom . here . ort . sp dx . Sp dx License Ċ import Ġcom . here . ort . utils . log Ċ Ċ import Ġjava . io . File Ċ import Ġjava . lang . IllegalArgumentException Ċ import Ġjava . time . Instant Ċ import Ġjava . util . Service Loader Ċ Ċ import Ġkotlinx . coroutines . run Blocking Ċ Ċ const Ġval ĠTO OL _ NAME Ġ= Ġ" scanner " Ċ const Ġval ĠHTTP _ CACHE _ PATH Ġ= Ġ"$ TOOL _ NAME / cache / http " Ċ Ċ /** Ċ Ġ* ĠThe Ġclass Ġto Ġrun Ġlicense Ġ/ Ġcopyright Ġsc anners . ĠThe Ġsignatures Ġof Ġpublic Ġfunctions Ġin Ġthis Ġclass Ġdefine Ġthe Ġlibrary Ċ Ġ* ĠAPI . Ċ Ġ*/ Ċ abstract Ġclass ĠScanner ( val Ġscanner Name : ĠString , Ġprotected Ġval Ġconfig : ĠScanner Configuration ) Ġ{ ĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġprivate Ġval ĠLO ADER Ġ= ĠService Loader . load ( Scanner Factory :: class . java ) !! ĊĊĠĠĠĠĠĠĠ Ġ/** ĊĠĠĠĠĠĠĠĠ Ġ* ĠThe Ġlist Ġof Ġall Ġavailable Ġsc anners Ġin Ġthe Ġclasspath . ĊĠĠĠĠĠĠĠĠ Ġ*/ ĊĠĠĠĠĠĠĠ Ġval ĠALL Ġby Ġlazy Ġ{ ĠLO ADER . iterator (). as Sequence (). toList () Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠScan Ġthe Ġlist Ġof Ġ[ packages ] Ġand Ġstore Ġthe Ġscan Ġresults Ġin Ġ[ output Directory ]. ĠThe Ġ[ download Directory ] Ġis Ġused Ġto ĊĠĠĠĠ Ġ* Ġdownload Ġthe Ġsource Ġcode Ġto Ġfor Ġscanning . Ġ[ Scan Result ] s Ġare Ġreturned Ġassociated Ġby Ġthe Ġ[ Package ]. ĠThe Ġmap Ġmay ĊĠĠĠĠ Ġ* Ġcontain Ġmultiple Ġresults Ġfor Ġthe Ġsame Ġ[ Package ] Ġif Ġthe Ġstorage Ġcontains Ġmore Ġthan Ġone Ġresult Ġfor Ġthe ĊĠĠĠĠ Ġ* Ġspecification Ġof Ġthis Ġscanner . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprotected Ġabstract Ġsuspend Ġfun Ġscan Packages ( ĊĠĠĠĠĠĠĠ Ġpackages : ĠList < Package >, ĊĠĠĠĠĠĠĠ Ġoutput Directory : ĠFile , ĊĠĠĠĠĠĠĠ Ġdownload Directory : ĠFile ĊĠĠĠ Ġ): ĠMap < Package , ĠList < Scan Result >> ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠReturn Ġthe Ġscanner - specific ĠSPDX Ġid string Ġfor Ġthe Ġgiven Ġ[ license ]. ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġget Sp dx License Id String ( license : ĠString ) Ġ= ĊĠĠĠĠĠĠĠ ĠSp dx License . for Id ( license )?. id Ġ?: Ġ" License Ref -$ scanner Name -$ license " ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠScan Ġthe Ġ[ Project ] s Ġand Ġ[ Package ] s Ġspecified Ġin Ġ[ ort Result File ] Ġand Ġstore Ġthe Ġscan Ġresults Ġin Ġ[ output Directory ]. ĊĠĠĠĠ Ġ* ĠThe Ġ[ download Directory ] Ġis Ġused Ġto Ġdownload Ġthe Ġsource Ġcode Ġto Ġfor Ġscanning . ĠReturn Ġscan Ġresults Ġas Ġan ĊĠĠĠĠ Ġ* Ġ[ Or t Result ]. ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġscan Or t Result ( ĊĠĠĠĠĠĠĠ Ġort Result File : ĠFile , ĊĠĠĠĠĠĠĠ Ġoutput Directory : ĠFile , ĊĠĠĠĠĠĠĠ Ġdownload Directory : ĠFile , ĊĠĠĠĠĠĠĠ Ġscopes To Scan : ĠSet < String > Ġ= Ġempty Set () ĊĠĠĠ Ġ): ĠO rt Result Ġ{ ĊĠĠĠĠĠĠĠ Ġrequire ( ort Result File . isFile ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" Provided Ġpath Ġfor Ġthe Ġconfiguration Ġdoes Ġnot Ġrefer Ġto Ġa Ġfile : Ġ${ ort Result File . absolute Path }" ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval ĠstartTime Ġ= ĠInstant . now () ĊĊĠĠĠĠĠĠĠ Ġval Ġort Result Ġ= Ġort Result File . readValue < Or t Result >() ĊĊĠĠĠĠĠĠĠ Ġrequire NotNull ( ort Result . analyzer ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" The Ġprovided ĠOR T Ġresult Ġfile Ġ'${ ort Result File . in variant Separ ators Path }' Ġdoes Ġnot Ġcontain Ġan Ġanalyzer Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" result ." ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġanalyzer Result Ġ= Ġort Result . analyzer !!. result ĊĊĠĠĠĠĠĠĠ Ġ// ĠAdd Ġthe Ġprojects Ġas Ġpackages Ġto Ġscan . ĊĠĠĠĠĠĠĠ Ġval Ġcon solid ated Project Package Map Ġ= ĠDown loader . con solid ate Project Package sBy V cs ( analyzer Result . projects ) ĊĠĠĠĠĠĠĠ Ġval Ġcon solid ated Reference Packages Ġ= Ġcon solid ated Project Package Map . keys . map Ġ{ Ġit . to Cur ated Package () Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġproject Scan Scopes Ġ= Ġif Ġ( scopes To Scan . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog . info Ġ{ Ġ" Limit ing Ġscan Ġto Ġscopes Ġ$ scopes To Scan ." Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġanalyzer Result . projects . map Ġ{ Ġproject Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġproject . scopes . map Ġ{ Ġit . name Ġ}. partition Ġ{ Ġit Ġin Ġscopes To Scan Ġ}. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠProject Scan Scopes ( project . id , Ġit . first . to Sorted Set (), Ġit . second . to Sorted Set ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġanalyzer Result . projects . map Ġ{ Ġproject Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġscopes Ġ= Ġproject . scopes . map Ġ{ Ġit . name Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠProject Scan Scopes ( project . id , Ġscopes . to Sorted Set (), Ġsorted Set Of ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ}. to Sorted Set () ĊĊĠĠĠĠĠĠĠ Ġval Ġcur ated Packages Ġ= Ġif Ġ( scopes To Scan . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcon solid ated Reference Packages Ġ+ Ġanalyzer Result . packages . filter Ġ{ Ġ( pkg , Ġ_) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġanalyzer Result . projects . any Ġ{ Ġproject Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġproject . scopes . any Ġ{ Ġit . name Ġin Ġscopes To Scan Ġ&& Ġpkg . id Ġin Ġit Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcon solid ated Reference Packages Ġ+ Ġanalyzer Result . packages ĊĠĠĠĠĠĠĠ Ġ}. to Sorted Set () ĊĊĠĠĠĠĠĠĠ Ġval Ġpackages To Scan Ġ= Ġcur ated Packages . map Ġ{ Ġit . pkg Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġresults Ġ= Ġrun Blocking Ġ{ Ġscan Packages ( packages To Scan , Ġoutput Directory , Ġdownload Directory ) Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġresult Containers Ġ= Ġresults . map Ġ{ Ġ( pkg , Ġresults ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠScan Result Container ( pkg . id , Ġresults ) ĊĠĠĠĠĠĠĠ Ġ}. to Sorted Set () ĊĊĠĠĠĠĠĠĠ Ġ// ĠAdd Ġscan Ġresults Ġfrom Ġde - d uplicated Ġproject Ġpackages Ġto Ġresult . ĊĠĠĠĠĠĠĠ Ġcon solid ated Project Package Map . forEach Ġ{ Ġ( reference Package , Ġde d uplicated Packages ) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresult Containers . find Ġ{ Ġit . id Ġ== Ġreference Package . id Ġ} ?. let Ġ{ Ġresult Container Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġde d uplicated Packages . forEach Ġ{ Ġde d uplicated Package Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġanalyzer Result . projects . find Ġ{ Ġit . id Ġ== Ġde d uplicated Package . id Ġ} ?. let Ġ{ Ġproject Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult Containers Ġ+= Ġfilter Project Scan Results ( project , Ġresult Container ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġ?: Ġthrow ĠIllegalArgumentException ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" Could Ġnot Ġfind Ġproject Ġ'${ ded uplicated Package . id . to Coordinates ()} '. " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġanalyzer Result . projects . find Ġ{ Ġit . id Ġ== Ġreference Package . id Ġ} ?. let Ġ{ Ġproject Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult Containers . remove ( result Container ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult Containers Ġ+= Ġfilter Project Scan Results ( project , Ġresult Container ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġ?: Ġthrow ĠIllegalArgumentException (" Could Ġnot Ġfind Ġproject Ġ'${ reference Package . id . to Coordinates ()} '. ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġscan Record Ġ= ĠScan Record ( project Scan Scopes , Ġresult Containers , ĠScan Results Storage . storage . stats ) ĊĊĠĠĠĠĠĠĠ Ġval ĠendTime Ġ= ĠInstant . now () ĊĊĠĠĠĠĠĠĠ Ġval Ġscanner Run Ġ= ĠScanner Run ( startTime , ĠendTime , ĠEnvironment (), Ġconfig , Ġscan Record ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠNote : ĠThis Ġover writes Ġany Ġexisting ĠScanner Run Ġfrom Ġthe Ġinput Ġfile . ĊĠĠĠĠĠĠĠ Ġreturn Ġort Result . copy ( scanner Ġ= Ġscanner Run ). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdata Ġ+= Ġort Result . data ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠFilter Ġthe Ġscan Ġresults Ġin Ġthe Ġ[ result Container ] Ġfor Ġonly Ġlicense Ġfindings Ġthat Ġare Ġin Ġthe Ġsame Ġsubdirectory Ġas ĊĠĠĠĠ Ġ* Ġthe Ġ[ project ] s Ġdefinition Ġfile . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġprivate Ġfun Ġfilter Project Scan Results ( project : ĠProject , Ġresult Container : ĠScan Result Container ): ĠScan Result Container Ġ{ ĊĠĠĠĠĠĠĠ Ġ// ĠDo Ġnot Ġfilter Ġthe Ġresults Ġif Ġthe Ġdefinition Ġfile Ġis Ġin Ġthe Ġroot Ġof Ġthe Ġrepository . ĊĠĠĠĠĠĠĠ Ġval Ġparent Path Ġ= ĠFile ( project . definition FilePath ). parent File ?. path Ġ?: Ġreturn Ġresult Container ĊĊĠĠĠĠĠĠĠ Ġval Ġfiltered Results Ġ= Ġresult Container . results . map Ġ{ Ġresult Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( result . pro venance . source Artifact Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠDo Ġnot Ġfilter Ġthe Ġresult Ġif Ġa Ġsource Ġartifact Ġwas Ġscanned . ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . filter Path ( parent Path ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġreturn ĠScan Result Container ( project . id , Ġfiltered Results ) ĊĠĠĠ Ġ} Ċ } Ċ