1+ package com .checkmarx .ast .iacrealtime ;
2+
3+ import com .checkmarx .ast .realtime .RealtimeLocation ;
4+ import com .fasterxml .jackson .annotation .JsonCreator ;
5+ import com .fasterxml .jackson .annotation .JsonIgnoreProperties ;
6+ import com .fasterxml .jackson .annotation .JsonInclude ;
7+ import com .fasterxml .jackson .annotation .JsonProperty ;
8+ import com .fasterxml .jackson .databind .ObjectMapper ;
9+ import com .fasterxml .jackson .databind .annotation .JsonDeserialize ;
10+ import lombok .Value ;
11+ import org .apache .commons .lang3 .StringUtils ;
12+ import org .slf4j .Logger ;
13+ import org .slf4j .LoggerFactory ;
14+
15+ import java .io .IOException ;
16+ import java .util .Collections ;
17+ import java .util .List ;
18+
19+ @ Value
20+ @ JsonDeserialize
21+ @ JsonInclude (JsonInclude .Include .NON_NULL )
22+ @ JsonIgnoreProperties (ignoreUnknown = true )
23+ public class IacRealtimeResults {
24+ private static final Logger log = LoggerFactory .getLogger (IacRealtimeResults .class );
25+ @ JsonProperty ("Results" ) List <Issue > results ; // Normalized list (array or single object)
26+
27+ @ JsonCreator
28+ public IacRealtimeResults (@ JsonProperty ("Results" ) List <Issue > results ) {
29+ this .results = results == null ? Collections .emptyList () : results ;
30+ }
31+
32+ @ Value
33+ @ JsonDeserialize
34+ @ JsonInclude (JsonInclude .Include .NON_NULL )
35+ @ JsonIgnoreProperties (ignoreUnknown = true )
36+ public static class Issue {
37+ @ JsonProperty ("Title" ) String title ;
38+ @ JsonProperty ("Description" ) String description ;
39+ @ JsonProperty ("SimilarityID" ) String similarityId ;
40+ @ JsonProperty ("FilePath" ) String filePath ;
41+ @ JsonProperty ("Severity" ) String severity ;
42+ @ JsonProperty ("ExpectedValue" ) String expectedValue ;
43+ @ JsonProperty ("ActualValue" ) String actualValue ;
44+ @ JsonProperty ("Locations" ) List <RealtimeLocation > locations ;
45+
46+ @ JsonCreator
47+ public Issue (@ JsonProperty ("Title" ) String title ,
48+ @ JsonProperty ("Description" ) String description ,
49+ @ JsonProperty ("SimilarityID" ) String similarityId ,
50+ @ JsonProperty ("FilePath" ) String filePath ,
51+ @ JsonProperty ("Severity" ) String severity ,
52+ @ JsonProperty ("ExpectedValue" ) String expectedValue ,
53+ @ JsonProperty ("ActualValue" ) String actualValue ,
54+ @ JsonProperty ("Locations" ) List <RealtimeLocation > locations ) {
55+ this .title = title ;
56+ this .description = description ;
57+ this .similarityId = similarityId ;
58+ this .filePath = filePath ;
59+ this .severity = severity ;
60+ this .expectedValue = expectedValue ;
61+ this .actualValue = actualValue ;
62+ this .locations = locations == null ? Collections .emptyList () : locations ;
63+ }
64+ }
65+
66+ public static IacRealtimeResults fromLine (String line ) {
67+ if (StringUtils .isBlank (line )) {
68+ return null ;
69+ }
70+ try {
71+ if (!isValidJSON (line )) {
72+ return null ;
73+ }
74+ ObjectMapper mapper = new ObjectMapper ();
75+ String trimmed = line .trim ();
76+ if (trimmed .startsWith ("[" )) {
77+ List <Issue > list = mapper .readValue (trimmed , mapper .getTypeFactory ().constructCollectionType (List .class , Issue .class ));
78+ return new IacRealtimeResults (list == null ? Collections .emptyList () : list );
79+ }
80+ if (trimmed .startsWith ("{" )) {
81+ Issue single = mapper .readValue (trimmed , Issue .class );
82+ return new IacRealtimeResults (Collections .singletonList (single ));
83+ }
84+ } catch (IOException e ) {
85+ log .debug ("Failed to parse iac realtime JSON line: {}" , line , e );
86+ }
87+ return null ;
88+ }
89+
90+ private static boolean isValidJSON (String json ) {
91+ try {
92+ new ObjectMapper ().readTree (json );
93+ return true ;
94+ } catch (IOException e ) {
95+ return false ;
96+ }
97+ }
98+ }
0 commit comments