@@ -6,14 +6,13 @@ namespace Microsoft.ComponentDetection.Detectors.Spdx;
66using System . IO ;
77using System . Linq ;
88using System . Security . Cryptography ;
9+ using System . Text . Json ;
910using System . Threading ;
1011using System . Threading . Tasks ;
1112using Microsoft . ComponentDetection . Contracts ;
1213using Microsoft . ComponentDetection . Contracts . Internal ;
1314using Microsoft . ComponentDetection . Contracts . TypedComponent ;
1415using Microsoft . Extensions . Logging ;
15- using Newtonsoft . Json ;
16- using Newtonsoft . Json . Linq ;
1716
1817/// <summary>
1918/// Spdx22ComponentDetector discover SPDX SBOM files in JSON format and create components with the information about
@@ -44,7 +43,7 @@ public Spdx22ComponentDetector(
4443
4544 public override IList < string > SearchPatterns => [ "*.spdx.json" ] ;
4645
47- protected override Task OnFileFoundAsync ( ProcessRequest processRequest , IDictionary < string , string > detectorArgs , CancellationToken cancellationToken = default )
46+ protected override async Task OnFileFoundAsync ( ProcessRequest processRequest , IDictionary < string , string > detectorArgs , CancellationToken cancellationToken = default )
4847 {
4948 this . Logger . LogDebug ( "Discovered SPDX2.2 manifest file at: {ManifestLocation}" , processRequest . ComponentStream . Location ) ;
5049 var file = processRequest . ComponentStream ;
@@ -56,31 +55,22 @@ protected override Task OnFileFoundAsync(ProcessRequest processRequest, IDiction
5655 // Reset buffer to starting position after hash generation.
5756 file . Stream . Seek ( 0 , SeekOrigin . Begin ) ;
5857
59- using var sr = new StreamReader ( file . Stream ) ;
60- using var reader = new JsonTextReader ( sr ) ;
61- var serializer = new JsonSerializer ( ) ;
62-
6358 try
6459 {
65- var document = serializer . Deserialize < JObject > ( reader ) ;
66- if ( document != null )
60+ using var document = await JsonDocument . ParseAsync ( file . Stream , cancellationToken : cancellationToken ) . ConfigureAwait ( false ) ;
61+ var root = document . RootElement ;
62+
63+ if ( this . IsSPDXVersionSupported ( root ) )
6764 {
68- if ( this . IsSPDXVersionSupported ( document ) )
69- {
70- var sbomComponent = this . ConvertJObjectToSbomComponent ( processRequest , document , hash ) ;
71- processRequest . SingleFileComponentRecorder . RegisterUsage ( new DetectedComponent ( sbomComponent ) ) ;
72- }
73- else
74- {
75- this . Logger . LogWarning ( "Discovered SPDX at {ManifestLocation} is not SPDX-2.2 document, skipping" , processRequest . ComponentStream . Location ) ;
76- }
65+ var sbomComponent = this . ConvertJsonElementToSbomComponent ( processRequest , root , hash ) ;
66+ processRequest . SingleFileComponentRecorder . RegisterUsage ( new DetectedComponent ( sbomComponent ) ) ;
7767 }
7868 else
7969 {
80- this . Logger . LogWarning ( "Discovered SPDX file at {ManifestLocation} is not a valid document, skipping" , processRequest . ComponentStream . Location ) ;
70+ this . Logger . LogWarning ( "Discovered SPDX at {ManifestLocation} is not SPDX-2.2 document, skipping" , processRequest . ComponentStream . Location ) ;
8171 }
8272 }
83- catch ( JsonReaderException )
73+ catch ( JsonException )
8474 {
8575 this . Logger . LogWarning ( "Unable to parse file at {ManifestLocation}, skipping" , processRequest . ComponentStream . Location ) ;
8676 }
@@ -89,25 +79,40 @@ protected override Task OnFileFoundAsync(ProcessRequest processRequest, IDiction
8979 {
9080 this . Logger . LogError ( e , "Error while processing SPDX file at {ManifestLocation}" , processRequest . ComponentStream . Location ) ;
9181 }
92-
93- return Task . CompletedTask ;
9482 }
9583
96- private bool IsSPDXVersionSupported ( JObject document ) => this . supportedSPDXVersions . Contains ( document [ "spdxVersion" ] ? . ToString ( ) , StringComparer . OrdinalIgnoreCase ) ;
84+ private bool IsSPDXVersionSupported ( JsonElement document )
85+ {
86+ if ( document . TryGetProperty ( "spdxVersion" , out var versionElement ) )
87+ {
88+ var version = versionElement . GetString ( ) ;
89+ return this . supportedSPDXVersions . Contains ( version , StringComparer . OrdinalIgnoreCase ) ;
90+ }
9791
98- private SpdxComponent ConvertJObjectToSbomComponent ( ProcessRequest processRequest , JObject document , string fileHash )
92+ return false ;
93+ }
94+
95+ private SpdxComponent ConvertJsonElementToSbomComponent ( ProcessRequest processRequest , JsonElement document , string fileHash )
9996 {
100- var sbomNamespace = document [ "documentNamespace" ] ? . ToString ( ) ;
101- var rootElements = document [ "documentDescribes" ] ? . ToObject < string [ ] > ( ) ;
102- var name = document [ "name" ] ? . ToString ( ) ;
103- var spdxVersion = document [ "spdxVersion" ] ? . ToString ( ) ;
97+ var sbomNamespace = document . TryGetProperty ( "documentNamespace" , out var nsElement ) ? nsElement . GetString ( ) : null ;
98+ var name = document . TryGetProperty ( "name" , out var nameElement ) ? nameElement . GetString ( ) : null ;
99+ var spdxVersion = document . TryGetProperty ( "spdxVersion" , out var versionElement2 ) ? versionElement2 . GetString ( ) : null ;
100+
101+ string [ ] rootElements = null ;
102+ if ( document . TryGetProperty ( "documentDescribes" , out var describesElement ) && describesElement . ValueKind == JsonValueKind . Array )
103+ {
104+ rootElements = describesElement . EnumerateArray ( )
105+ . Select ( e => e . GetString ( ) )
106+ . Where ( s => s != null )
107+ . ToArray ( ) ;
108+ }
104109
105- if ( rootElements ? . Length > 1 )
110+ if ( rootElements is { Length : > 1 } )
106111 {
107112 this . Logger . LogWarning ( "SPDX file at {ManifestLocation} has more than one element in documentDescribes, first will be selected as root element." , processRequest . ComponentStream . Location ) ;
108113 }
109114
110- if ( rootElements != null && rootElements . Length == 0 )
115+ if ( rootElements is { Length : 0 } )
111116 {
112117 this . Logger . LogWarning ( "SPDX file at {ManifestLocation} does not have root elements in documentDescribes section, considering SPDXRef-Document as a root element." , processRequest . ComponentStream . Location ) ;
113118 }
0 commit comments