Skip to content

Commit b351f8d

Browse files
authored
Refactor build scan table
1 parent 1f01aaf commit b351f8d

File tree

11 files changed

+647
-543
lines changed

11 files changed

+647
-543
lines changed

build-info-client/src/main/java/org/jfrog/build/client/artifactoryXrayResponse/Issue.java

+14
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,18 @@ public void setCve(String cve) {
108108
public String toString() {
109109
return ToStringBuilder.reflectionToString(this);
110110
}
111+
112+
public enum IssueType {
113+
SECURITY,
114+
LICENSE
115+
}
116+
117+
public IssueType getIssueType() {
118+
if ("Security".equals(this.getType())) {
119+
return IssueType.SECURITY;
120+
} else if ("License".equals(this.getType())) {
121+
return IssueType.LICENSE;
122+
}
123+
return null;
124+
}
111125
}

build-info-extractor/src/main/java/org/jfrog/build/extractor/buildScanTable/BuildScanTableElement.java

-51
This file was deleted.

build-info-extractor/src/main/java/org/jfrog/build/extractor/buildScanTable/BuildScanTableHelper.java

+25-72
Original file line numberDiff line numberDiff line change
@@ -2,87 +2,43 @@
22

33
import org.jfrog.build.api.util.Log;
44
import org.jfrog.build.client.artifactoryXrayResponse.*;
5-
import org.jfrog.build.extractor.scan.Severity;
6-
7-
import java.util.*;
85

96
import static org.jfrog.build.api.util.CommonUtils.emptyIfNull;
107

118
/***
12-
* Helper for printing build scan results as a violations table to log.
9+
* Helper for printing build scan results as violations tables to log.
1310
*/
1411
@SuppressWarnings("unused")
1512
public class BuildScanTableHelper {
1613
private ArtifactoryXrayResponse scanResult;
17-
private Map<Severity, Set<BuildScanTableElement>> table;
1814
private Log log;
19-
private int longestDisplayName = 0;
20-
private String tableFormat = "";
21-
public String TABLE_HEADLINE = "Xray Scan Summary:";
22-
public List<String> TABLE_HEADERS = Arrays.asList("#", "Component", "Severity", "Type");
15+
16+
SecurityViolationsTable securityViolationsTable;
17+
LicenseViolationsTable licenseViolationsTable;
2318

2419
@SuppressWarnings("unused")
25-
public void PrintTable(ArtifactoryXrayResponse scanResult, Log log) {
20+
public void printTable(ArtifactoryXrayResponse scanResult, Log log) {
2621
this.scanResult = scanResult;
2722
this.log = log;
23+
securityViolationsTable = new SecurityViolationsTable(log);
24+
licenseViolationsTable = new LicenseViolationsTable(log);
2825
generateResultTable();
29-
updateTableFormat();
30-
print();
26+
doPrintTables();
3127
}
3228

3329
/***
34-
* Prints the generated build scan table to log.
35-
* Table is rendered with the table format.
30+
* Prints the generated violations tables to log.
3631
*/
37-
private void print() {
38-
int line = 1;
39-
Severity[] severities = Severity.values();
40-
41-
// Print table headline.
42-
log.info(TABLE_HEADLINE);
43-
// Print column headers.
44-
printLine(TABLE_HEADERS.toArray());
45-
46-
// Print lines of violations by descending severity.
47-
for (int i = severities.length - 1; i >= 0; i--) {
48-
Severity severity = severities[i];
49-
Set<BuildScanTableElement> elements = table.get(severity);
50-
if (elements == null) {
51-
continue;
52-
}
53-
for (BuildScanTableElement element : elements) {
54-
printLine(line, element.getFileDisplayName(), severity.getSeverityName(), element.getIssueType());
55-
line++;
56-
}
57-
}
32+
private void doPrintTables() {
33+
securityViolationsTable.printTable();
5834
log.info("");
59-
}
60-
61-
private void printLine(Object... args) {
62-
log.info(String.format(tableFormat, args));
63-
}
64-
65-
/***
66-
* Updates table format after longestDisplayName is known.
67-
* Format aligns elements to the left.
68-
* Padding on a column must be longer than the longest element in that column.
69-
*/
70-
private void updateTableFormat() {
71-
// Index (assuming 5 digits is sufficient).
72-
tableFormat = "%-6s"
73-
// Display name (plus space).
74-
+ "%-" + (longestDisplayName + 5) + "s"
75-
// Severity (Longest is 'Information').
76-
+ "%-15s"
77-
// Type (Longest is 'Security').
78-
+ "%-10s";
35+
licenseViolationsTable.printTable();
7936
}
8037

8138
/***
8239
* Loops over all alerts and adds infected files with required information.
8340
*/
8441
private void generateResultTable() {
85-
table = new HashMap<>();
8642
for (Alert alert : emptyIfNull(scanResult.getAlerts())) {
8743
for (Issue issue : emptyIfNull(alert.getIssues())) {
8844
for (ImpactedArtifact impactedArtifact : emptyIfNull(issue.getImpactedArtifacts())) {
@@ -94,23 +50,20 @@ private void generateResultTable() {
9450
}
9551
}
9652

53+
/**
54+
* Add a violation to the corresponding table.
55+
*
56+
* @param issue Issue that caused violation.
57+
* @param infectedFile Infected file.
58+
*/
9759
private void addElement(Issue issue, InfectedFile infectedFile) {
98-
// Create table element.
99-
Severity severity = Severity.fromString(issue.getSeverity());
100-
BuildScanTableElement buildScanTableElement = new BuildScanTableElement(infectedFile.getDisplayName(), infectedFile.getSha256(),
101-
issue.getType(), issue.getSummary(), issue.getDescription());
102-
103-
// Add element to table.
104-
Set<BuildScanTableElement> elements = table.get(severity);
105-
if (elements == null) {
106-
elements = new HashSet<>();
107-
}
108-
elements.add(buildScanTableElement);
109-
table.put(severity, elements);
110-
111-
// Update longest display name if longer.
112-
if (infectedFile.getDisplayName() != null && infectedFile.getDisplayName().length() > longestDisplayName) {
113-
longestDisplayName = infectedFile.getDisplayName().length();
60+
Issue.IssueType issueType = issue.getIssueType();
61+
if (issueType == Issue.IssueType.SECURITY) {
62+
securityViolationsTable.addElement(issue, infectedFile);
63+
} else if (issueType == Issue.IssueType.LICENSE) {
64+
licenseViolationsTable.addElement(issue, infectedFile);
65+
} else {
66+
throw new IllegalArgumentException(String.format("Illegal issue type '%s'. Expecting either 'Security' or 'License'", issue.getType()));
11467
}
11568
}
11669
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.jfrog.build.extractor.buildScanTable;
2+
3+
import org.jfrog.build.api.util.Log;
4+
import org.jfrog.build.client.artifactoryXrayResponse.InfectedFile;
5+
import org.jfrog.build.client.artifactoryXrayResponse.Issue;
6+
7+
import java.util.Objects;
8+
9+
public class LicenseViolationsTable extends ScanTableBase {
10+
public static final String LICENSE_VIOLATIONS_TABLE_HEADLINE = "License Compliance Violations";
11+
12+
protected LicenseViolationsTable(Log log) {
13+
super(log);
14+
}
15+
16+
protected String getHeadline() {
17+
return LICENSE_VIOLATIONS_TABLE_HEADLINE;
18+
}
19+
20+
protected String[] getHeaders() {
21+
return new String[]{"#", "Severity", "Component"};
22+
}
23+
24+
protected String getTableFormat() {
25+
return super.getFormatBase(longestDisplayName);
26+
}
27+
28+
protected String getEmptyTableLine() {
29+
return "No license compliance violations were found";
30+
}
31+
32+
protected void addElement(Issue issue, InfectedFile infectedFile) {
33+
// Create table element.
34+
LicenseTableElement element = new LicenseTableElement(infectedFile.getDisplayName(), infectedFile.getSha256(),
35+
issue.getSummary(), issue.getDescription());
36+
super.addElement(table, issue, element);
37+
// Update the longest display name if longer.
38+
if (infectedFile.getDisplayName() != null && infectedFile.getDisplayName().length() > longestDisplayName) {
39+
longestDisplayName = infectedFile.getDisplayName().length();
40+
}
41+
}
42+
43+
protected void printTable() {
44+
super.printTable(table);
45+
}
46+
47+
private static class LicenseTableElement extends TableElementBase {
48+
LicenseTableElement(String fileDisplayName, String fileSha256,
49+
String issueSummary, String issueDescription) {
50+
super(fileDisplayName, fileSha256, issueSummary, issueDescription);
51+
}
52+
53+
@Override
54+
protected Object[] getLineArgs(int line, String severityName) {
55+
return new Object[]{line, severityName, this.getFileDisplayName()};
56+
}
57+
58+
@Override
59+
public boolean equals(Object o) {
60+
if (this == o) return true;
61+
if (o == null || getClass() != o.getClass()) return false;
62+
LicenseTableElement that = (LicenseTableElement) o;
63+
return Objects.equals(fileDisplayName, that.fileDisplayName) &&
64+
Objects.equals(fileSha256, that.fileSha256) &&
65+
Objects.equals(issueSummary, that.issueSummary) &&
66+
Objects.equals(issueDescription, that.issueDescription);
67+
}
68+
69+
@Override
70+
public int hashCode() {
71+
return Objects.hash(fileDisplayName, fileSha256, issueSummary, issueDescription);
72+
}
73+
}
74+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package org.jfrog.build.extractor.buildScanTable;
2+
3+
import org.jfrog.build.api.util.Log;
4+
import org.jfrog.build.client.artifactoryXrayResponse.Issue;
5+
import org.jfrog.build.extractor.scan.Severity;
6+
7+
import java.util.HashMap;
8+
import java.util.HashSet;
9+
import java.util.Map;
10+
import java.util.Set;
11+
12+
/**
13+
* Base class for violations tables printed by {@link BuildScanTableHelper}
14+
*/
15+
abstract class ScanTableBase {
16+
private final Log log;
17+
protected int longestDisplayName = 0;
18+
protected final Map<Severity, Set<TableElementBase>> table = new HashMap<>();
19+
20+
protected ScanTableBase(Log log) {
21+
this.log = log;
22+
}
23+
24+
protected abstract String getHeadline();
25+
26+
protected abstract String[] getHeaders();
27+
28+
protected abstract String getTableFormat();
29+
30+
protected abstract String getEmptyTableLine();
31+
32+
protected String getFormatBase(int longestDisplayName) {
33+
// Index (assuming 5 digits is sufficient).
34+
return "%-6s"
35+
// Severity (Longest is 'Information').
36+
+ "%-14s"
37+
// Display name (plus space).
38+
+ "%-" + (longestDisplayName + 3) + "s";
39+
}
40+
41+
private void printFormattedLine(Object... args) {
42+
log.info(String.format(getTableFormat(), args));
43+
}
44+
45+
protected void addElement(Map<Severity, Set<TableElementBase>> table, Issue issue, TableElementBase element) {
46+
Severity severity = Severity.fromString(issue.getSeverity());
47+
Set<TableElementBase> elements = table.get(severity);
48+
if (elements == null) {
49+
elements = new HashSet<>();
50+
}
51+
elements.add(element);
52+
table.put(severity, elements);
53+
}
54+
55+
protected void printTable(Map<Severity, Set<TableElementBase>> table) {
56+
int line = 1;
57+
Severity[] severities = Severity.values();
58+
59+
// Print table headline.
60+
log.info(getHeadline());
61+
62+
// If table is empty, print the no violations found line and return.
63+
if (table.isEmpty()) {
64+
log.info(getEmptyTableLine());
65+
log.info("");
66+
return;
67+
}
68+
69+
// Print column headers.
70+
printFormattedLine((Object[]) getHeaders());
71+
72+
// Print lines of violations by descending severity.
73+
for (int i = severities.length - 1; i >= 0; i--) {
74+
Severity severity = severities[i];
75+
Set<TableElementBase> elements = table.get(severity);
76+
if (elements == null) {
77+
continue;
78+
}
79+
for (TableElementBase element : elements) {
80+
printFormattedLine(element.getLineArgs(line, severity.getSeverityName()));
81+
line++;
82+
}
83+
}
84+
log.info("");
85+
}
86+
87+
/**
88+
* Base class for elements of the violations tables
89+
*/
90+
protected abstract static class TableElementBase {
91+
protected final String fileDisplayName;
92+
// Following fields are for the set's uniqueness only:
93+
protected final String fileSha256;
94+
protected final String issueSummary;
95+
protected final String issueDescription;
96+
97+
protected TableElementBase(String fileDisplayName, String fileSha256,
98+
String issueSummary, String issueDescription) {
99+
this.fileDisplayName = fileDisplayName;
100+
this.fileSha256 = fileSha256;
101+
this.issueSummary = issueSummary;
102+
this.issueDescription = issueDescription;
103+
}
104+
105+
protected String getFileDisplayName() {
106+
return fileDisplayName == null ? "" : fileDisplayName;
107+
}
108+
109+
protected abstract Object[] getLineArgs(int line, String severityName);
110+
}
111+
}

0 commit comments

Comments
 (0)