Skip to content

Commit 22be943

Browse files
extract commercial averages table to separate class (#78)
1 parent 6be334c commit 22be943

File tree

6 files changed

+386
-85
lines changed

6 files changed

+386
-85
lines changed

plugin/src/main/java/org/owasp/benchmarkutils/score/BenchmarkScore.java

Lines changed: 8 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import java.nio.file.Path;
3030
import java.nio.file.Paths;
3131
import java.security.SecureRandom;
32-
import java.text.DecimalFormat;
3332
import java.util.ArrayList;
3433
import java.util.Calendar;
3534
import java.util.HashMap;
@@ -54,6 +53,7 @@
5453
import org.owasp.benchmarkutils.score.report.ScatterHome;
5554
import org.owasp.benchmarkutils.score.report.ScatterInterpretation;
5655
import org.owasp.benchmarkutils.score.report.ScatterVulns;
56+
import org.owasp.benchmarkutils.score.report.html.CommercialAveragesTable;
5757
import org.owasp.benchmarkutils.score.report.html.OverallStatsTable;
5858
import org.owasp.benchmarkutils.score.report.html.ToolScorecard;
5959
import org.owasp.benchmarkutils.score.report.html.VulnerabilityStatsTable;
@@ -265,7 +265,6 @@ public static void main(String[] args) {
265265
// Steps 4 & 5: Read the expected results so we know what each tool 'should do' and each
266266
// tool's results file. a) is for 'mixed' mode, and b) is for normal mode
267267
try {
268-
269268
if (config.mixedMode) {
270269

271270
if (!resultsFileOrDir.isDirectory()) {
@@ -581,8 +580,6 @@ private static void process(
581580
ToolResults metrics = calculateMetrics(scores);
582581
metrics.setScanTime(rawToolResults.getTime());
583582

584-
// This has the side effect of also generating the tool's report in the
585-
// scoreCardDir.
586583
Tool tool =
587584
new Tool(
588585
rawToolResults,
@@ -983,13 +980,7 @@ private static String produceResultsFile(TestSuiteResults actual, File scoreCard
983980
*/
984981
private static void generateVulnerabilityScorecards(
985982
Set<Tool> tools, Set<String> catSet, File scoreCardDir) {
986-
StringBuilder htmlForCommercialAverages = null;
987-
988-
int commercialToolTotal = 0;
989-
int numberOfVulnCategories = 0;
990-
int commercialLowTotal = 0;
991-
int commercialAveTotal = 0;
992-
int commercialHighTotal = 0;
983+
CommercialAveragesTable commercialAveragesTable = new CommercialAveragesTable();
993984

994985
// A side effect of this method is to calculate these averages
995986
averageCommercialToolResults = new HashMap<String, CategoryResults>();
@@ -1003,7 +994,6 @@ private static void generateVulnerabilityScorecards(
1003994

1004995
for (String cat : catSet) {
1005996
try {
1006-
1007997
// Generate a comparison chart for all tools for this vuln category. When
1008998
// constructed, scatter contains the Overall, Non-commercial, and Commercial stats
1009999
// for this category across all tools.
@@ -1065,88 +1055,22 @@ private static void generateVulnerabilityScorecards(
10651055

10661056
Files.write(htmlFile.toPath(), html.getBytes());
10671057

1068-
// Now build up the commercial stats scorecard if there are at 2+ commercial tools
1058+
// Only build commercial stats scorecard if there are at 2+ commercial tools
10691059
if (scatter.getCommercialToolCount() > 1) {
1070-
if (htmlForCommercialAverages == null) {
1071-
commercialToolTotal = scatter.getCommercialToolCount();
1072-
htmlForCommercialAverages = new StringBuilder();
1073-
htmlForCommercialAverages.append("<table class=\"table\">\n");
1074-
htmlForCommercialAverages.append("<tr>");
1075-
htmlForCommercialAverages.append("<th>Vulnerability Category</th>");
1076-
htmlForCommercialAverages.append("<th>Low Tool Type</th>");
1077-
htmlForCommercialAverages.append("<th>Low Score</th>");
1078-
htmlForCommercialAverages.append("<th>Ave Score</th>");
1079-
htmlForCommercialAverages.append("<th>High Score</th>");
1080-
htmlForCommercialAverages.append("<th>High Tool Type</th>");
1081-
htmlForCommercialAverages.append("</tr>\n");
1082-
} // if 1st time through
1083-
1084-
numberOfVulnCategories++;
1085-
1086-
String style = "";
1087-
htmlForCommercialAverages.append("<tr>");
1088-
htmlForCommercialAverages.append("<td>" + cat + "</td>");
1089-
htmlForCommercialAverages.append(
1090-
"<td>" + scatter.getCommercialLowToolType() + "</td>");
1091-
if (scatter.getCommercialLow() <= 10) style = "class=\"danger\"";
1092-
else if (scatter.getCommercialLow() >= 50) style = "class=\"success\"";
1093-
htmlForCommercialAverages.append(
1094-
"<td " + style + ">" + scatter.getCommercialLow() + "</td>");
1095-
commercialLowTotal += scatter.getCommercialLow();
1096-
htmlForCommercialAverages.append("<td>" + scatter.getCommercialAve() + "</td>");
1097-
commercialAveTotal += scatter.getCommercialAve();
1098-
if (scatter.getCommercialHigh() <= 10) style = "class=\"danger\"";
1099-
else if (scatter.getCommercialHigh() >= 50) style = "class=\"success\"";
1100-
htmlForCommercialAverages.append(
1101-
"<td " + style + ">" + scatter.getCommercialHigh() + "</td>");
1102-
commercialHighTotal += scatter.getCommercialHigh();
1103-
htmlForCommercialAverages.append(
1104-
"<td>" + scatter.getCommercialHighToolType() + "</td>");
1105-
htmlForCommercialAverages.append("</tr>\n");
1106-
} // if more than 1 commercial tool
1060+
commercialAveragesTable.add(scatter);
1061+
}
11071062

11081063
} catch (IOException e) {
11091064
System.out.println("Error generating vulnerability summaries: " + e.getMessage());
11101065
e.printStackTrace();
11111066
}
11121067
} // end for loop
11131068

1114-
// if we computed a commercial average, then add the last row to the table AND create the
1115-
// file and write the HTML to it.
1116-
if (htmlForCommercialAverages != null) {
1117-
1118-
htmlForCommercialAverages.append("<tr>");
1119-
htmlForCommercialAverages.append(
1120-
"<td>Average across all categories for " + commercialToolTotal + " tools</td>");
1121-
htmlForCommercialAverages.append("<td></td>");
1122-
htmlForCommercialAverages.append(
1123-
"<td>"
1124-
+ new DecimalFormat("0.0")
1125-
.format(
1126-
(float) commercialLowTotal
1127-
/ (float) numberOfVulnCategories)
1128-
+ "</td>");
1129-
htmlForCommercialAverages.append(
1130-
"<td>"
1131-
+ new DecimalFormat("0.0")
1132-
.format(
1133-
(float) commercialAveTotal
1134-
/ (float) numberOfVulnCategories)
1135-
+ "</td>");
1136-
htmlForCommercialAverages.append(
1137-
"<td>"
1138-
+ new DecimalFormat("0.0")
1139-
.format(
1140-
(float) commercialHighTotal
1141-
/ (float) numberOfVulnCategories)
1142-
+ "</td>");
1143-
htmlForCommercialAverages.append("<td></td>");
1144-
htmlForCommercialAverages.append("</tr>\n");
1145-
htmlForCommercialAverages.append("</table>\n");
1146-
1069+
if (commercialAveragesTable.hasEntries()) {
11471070
try {
11481071
commercialAveScorecardFilename =
11491072
TESTSUITE + "_v" + TESTSUITEVERSION + "_Scorecard_for_Commercial_Tools";
1073+
11501074
Path htmlfile =
11511075
Paths.get(
11521076
scoreCardDir.getAbsolutePath()
@@ -1164,8 +1088,7 @@ private static void generateVulnerabilityScorecards(
11641088
html = html.replace("${version}", TESTSUITEVERSION);
11651089
html = html.replace("${projectlink}", BenchmarkScore.PROJECTLINKENTRY);
11661090

1167-
String table = htmlForCommercialAverages.toString();
1168-
html = html.replace("${table}", table);
1091+
html = html.replace("${table}", commercialAveragesTable.render());
11691092
html = html.replace("${tprlabel}", config.tprLabel);
11701093
html =
11711094
html.replace(

plugin/src/main/java/org/owasp/benchmarkutils/score/report/Formats.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,7 @@
2222
public class Formats {
2323

2424
public static final DecimalFormat twoDecimalPlacesPercentage = new DecimalFormat("#0.00%");
25+
26+
public static final DecimalFormat singleDecimalPlaceNumber = new DecimalFormat("0.0");
2527
public static final DecimalFormat fourDecimalPlacesNumber = new DecimalFormat("#0.0000");
2628
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/**
2+
* OWASP Benchmark Project
3+
*
4+
* <p>This file is part of the Open Web Application Security Project (OWASP) Benchmark Project For
5+
* details, please see <a
6+
* href="https://owasp.org/www-project-benchmark/">https://owasp.org/www-project-benchmark/</a>.
7+
*
8+
* <p>The OWASP Benchmark is free software: you can redistribute it and/or modify it under the terms
9+
* of the GNU General Public License as published by the Free Software Foundation, version 2.
10+
*
11+
* <p>The OWASP Benchmark is distributed in the hope that it will be useful, but WITHOUT ANY
12+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13+
* PURPOSE. See the GNU General Public License for more details.
14+
*
15+
* @author Sascha Knoop
16+
* @created 2024
17+
*/
18+
package org.owasp.benchmarkutils.score.report.html;
19+
20+
import static org.owasp.benchmarkutils.score.report.Formats.singleDecimalPlaceNumber;
21+
22+
import java.util.ArrayList;
23+
import java.util.List;
24+
import org.owasp.benchmarkutils.score.report.ScatterVulns;
25+
26+
public class CommercialAveragesTable {
27+
28+
private final List<ScatterVulns> entries = new ArrayList<>();
29+
30+
public void add(ScatterVulns scatter) {
31+
entries.add(scatter);
32+
}
33+
34+
public String render() {
35+
HtmlStringBuilder htmlBuilder = new HtmlStringBuilder();
36+
37+
htmlBuilder.beginTable("table");
38+
39+
addHeaderTo(htmlBuilder);
40+
41+
entries.forEach(scatter -> appendRowTo(htmlBuilder, scatter));
42+
43+
addFooterTo(htmlBuilder);
44+
45+
htmlBuilder.endTable();
46+
47+
return htmlBuilder.toString();
48+
}
49+
50+
private int commercialToolTotal() {
51+
return entries.get(0).getCommercialToolCount();
52+
}
53+
54+
private void addHeaderTo(HtmlStringBuilder htmlBuilder) {
55+
htmlBuilder.beginTr();
56+
htmlBuilder.th("Vulnerability Category");
57+
htmlBuilder.th("Low Tool Type");
58+
htmlBuilder.th("Low Score");
59+
htmlBuilder.th("Ave Score");
60+
htmlBuilder.th("High Score");
61+
htmlBuilder.th("High Tool Type");
62+
htmlBuilder.endTr();
63+
}
64+
65+
private void appendRowTo(HtmlStringBuilder htmlBuilder, ScatterVulns scatter) {
66+
htmlBuilder.beginTr();
67+
htmlBuilder.td(scatter.CATEGORY);
68+
htmlBuilder.td(scatter.getCommercialLowToolType() + "");
69+
70+
htmlBuilder.td(scatter.getCommercialLow(), cssClassFor(scatter.getCommercialLow()));
71+
htmlBuilder.td(scatter.getCommercialAve());
72+
73+
htmlBuilder.td(scatter.getCommercialHigh(), cssClassFor(scatter.getCommercialHigh()));
74+
htmlBuilder.td(scatter.getCommercialHighToolType() + "");
75+
htmlBuilder.endTr();
76+
}
77+
78+
private static String cssClassFor(int commercialLow) {
79+
String cssClass = null;
80+
81+
if (commercialLow <= 10) {
82+
cssClass = "danger";
83+
} else if (commercialLow >= 50) {
84+
cssClass = "success";
85+
}
86+
87+
return cssClass;
88+
}
89+
90+
private void addFooterTo(HtmlStringBuilder htmlBuilder) {
91+
htmlBuilder.beginTr();
92+
htmlBuilder.td("Average across all categories for " + commercialToolTotal() + " tools");
93+
htmlBuilder.td("");
94+
htmlBuilder.td(
95+
singleDecimalPlaceNumber.format(
96+
(float) commercialLowTotal() / (float) entries.size()));
97+
htmlBuilder.td(
98+
singleDecimalPlaceNumber.format(
99+
(float) commercialAveTotal() / (float) entries.size()));
100+
htmlBuilder.td(
101+
singleDecimalPlaceNumber.format(
102+
(float) commercialHighTotal() / (float) entries.size()));
103+
htmlBuilder.td("");
104+
htmlBuilder.endTr();
105+
}
106+
107+
// formattedRatio
108+
109+
private int commercialHighTotal() {
110+
return entries.stream().mapToInt(ScatterVulns::getCommercialHigh).sum();
111+
}
112+
113+
private int commercialAveTotal() {
114+
return entries.stream().mapToInt(ScatterVulns::getCommercialAve).sum();
115+
}
116+
117+
private int commercialLowTotal() {
118+
return entries.stream().mapToInt(ScatterVulns::getCommercialLow).sum();
119+
}
120+
121+
public boolean hasEntries() {
122+
return !entries.isEmpty();
123+
}
124+
}

plugin/src/main/java/org/owasp/benchmarkutils/score/report/html/HtmlStringBuilder.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,16 @@ public HtmlStringBuilder td(long content) {
9999
return this;
100100
}
101101

102+
public HtmlStringBuilder td(long content, String cssClass) {
103+
if (cssClass == null) {
104+
return td(content);
105+
}
106+
107+
sb.append("<td class=\"").append(cssClass).append("\">").append(content).append("</td>");
108+
109+
return this;
110+
}
111+
102112
public HtmlStringBuilder td(double content) {
103113
sb.append("<td>").append(content).append("</td>");
104114

plugin/src/test/java/org/owasp/benchmarkutils/score/report/FormatsTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import static org.junit.jupiter.api.Assertions.assertEquals;
2121
import static org.owasp.benchmarkutils.score.report.Formats.fourDecimalPlacesNumber;
22+
import static org.owasp.benchmarkutils.score.report.Formats.singleDecimalPlaceNumber;
2223
import static org.owasp.benchmarkutils.score.report.Formats.twoDecimalPlacesPercentage;
2324

2425
import org.junit.jupiter.api.Test;
@@ -34,4 +35,9 @@ void hasFormatterForTwoDecimalPlacesPercentage() {
3435
void hasFormatterForFourDecimalPlaces() {
3536
assertEquals("12.3457", fourDecimalPlacesNumber.format(12.345678));
3637
}
38+
39+
@Test
40+
void hasFormatterForSingleDecimalPlace() {
41+
assertEquals("12.3", singleDecimalPlaceNumber.format(12.345678));
42+
}
3743
}

0 commit comments

Comments
 (0)