Skip to content

Commit 494ad1a

Browse files
authored
Handle comma-separated filename inputs for Sonar issues JSON and Sonar hotspots JSON (#365)
Issue: #364 Example of running a list of sonar findings files: ``` ./gradlew :core-codemods:run --args='--output /Users/iwa/Documents/GitHub/WebGoat_12_23/WebGoat_12_23.codetf --verbose --sonar-issues-json /Users/iwa/Desktop/sonar1.json,/Users/iwa/Desktop/sonar2.json --log-format human /Users/iwa/Documents/GitHub/WebGoat_12_23/' ``` Sonar hotspot CLI input was the only update since there's no implementation for it yet
1 parent 80c4c39 commit 494ad1a

File tree

17 files changed

+117
-42
lines changed

17 files changed

+117
-42
lines changed

core-codemods/src/test/java/io/codemodder/codemods/AddMissingOverrideCodemodTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
codemodType = AddMissingOverrideCodemod.class,
88
testResourceDir = "add-missing-override-s1161",
99
renameTestFile = "src/main/java/SqlInjectionLesson10b.java",
10-
dependencies = {})
10+
dependencies = {},
11+
sonarIssuesJsonFiles = {"sonar-issues_1.json", "sonar-issues_2.json"})
1112
final class AddMissingOverrideCodemodTest implements CodemodTestMixin {}

core-codemods/src/test/resources/add-missing-override-s1161/sonar-issues.json renamed to core-codemods/src/test/resources/add-missing-override-s1161/sonar-issues_1.json

File renamed without changes.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"total": 1,
3+
"p": 1,
4+
"ps": 500,
5+
"paging": {
6+
"pageIndex": 1,
7+
"pageSize": 500,
8+
"total": 1
9+
},
10+
"effortTotal": 5,
11+
"debtTotal": 5,
12+
"issues": [
13+
],
14+
"components": [
15+
{
16+
"organization": "nahsra",
17+
"key": "nahsra_WebGoat_10_23",
18+
"uuid": "AYvtqxxxzY4Rr5NHn4Om",
19+
"enabled": true,
20+
"qualifier": "TRK",
21+
"name": "WebGoat_10_23",
22+
"longName": "WebGoat_10_23"
23+
},
24+
{
25+
"organization": "nahsra",
26+
"key": "nahsra_WebGoat_10_23:src/main/java/org/owasp/webgoat/lessons/sqlinjection/mitigation/SqlInjectionLesson10b.java",
27+
"uuid": "AYvtrjqILCzGLicz7AX9",
28+
"enabled": true,
29+
"qualifier": "FIL",
30+
"name": "SqlInjectionLesson10b.java",
31+
"longName": "src/main/java/org/owasp/webgoat/lessons/sqlinjection/mitigation/SqlInjectionLesson10b.java",
32+
"path": "src/main/java/org/owasp/webgoat/lessons/sqlinjection/mitigation/SqlInjectionLesson10b.java"
33+
}
34+
],
35+
"organizations": [
36+
{
37+
"key": "nahsra",
38+
"name": "Arshan Dabirsiaghi"
39+
}
40+
],
41+
"facets": []
42+
}

framework/codemodder-base/src/main/java/io/codemodder/CLI.java

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,9 @@ final class CLI implements Callable<Integer> {
118118
@CommandLine.Option(
119119
names = {"--sonar-issues-json"},
120120
description =
121-
"a path to a file containing the result of a call to the Sonar Web API Issues endpoint")
122-
private Path sonarIssuesJsonFilePath;
121+
"comma-separated set of path(s) to file(s) containing the result of a call to the Sonar Web API Issues endpoint",
122+
split = ",")
123+
private List<String> sonarIssuesJsonFilePaths;
123124

124125
@CommandLine.Option(
125126
names = {"--defectdojo-findings-json"},
@@ -130,8 +131,9 @@ final class CLI implements Callable<Integer> {
130131
@CommandLine.Option(
131132
names = {"--sonar-hotspots-json"},
132133
description =
133-
"a path to a file containing the result of a call to the Sonar Web API Hotspots endpoint")
134-
private Path sonarHotspotsJsonFilePath;
134+
"comma-separated set of path(s) to file(s) containing the result of a call to the Sonar Web API Hotspots endpoint",
135+
split = ",")
136+
private List<Path> sonarHotspotsJsonFilePaths;
135137

136138
@CommandLine.Option(
137139
names = {"--contrast-vulnerabilities-xml"},
@@ -378,8 +380,8 @@ public Integer call() throws IOException {
378380

379381
// create the loader
380382
CodeDirectory codeDirectory = new DefaultCodeDirectory(projectPath);
381-
List<Path> sarifFiles =
382-
sarifs != null ? sarifs.stream().map(Path::of).collect(Collectors.toList()) : List.of();
383+
List<Path> sarifFiles = convertToPaths(sarifs);
384+
List<Path> sonarIssuesJsonFiles = convertToPaths(sonarIssuesJsonFilePaths);
383385
Map<String, List<RuleSarif>> pathSarifMap =
384386
SarifParser.create().parseIntoMap(sarifFiles, codeDirectory);
385387
List<ParameterArgument> codemodParameters =
@@ -394,7 +396,7 @@ public Integer call() throws IOException {
394396
filePaths,
395397
pathSarifMap,
396398
codemodParameters,
397-
sonarIssuesJsonFilePath,
399+
sonarIssuesJsonFiles,
398400
defectDojoFindingsJsonFilePath,
399401
contrastVulnerabilitiesXmlFilePath);
400402
List<CodemodIdPair> codemods = loader.getCodemods();
@@ -513,6 +515,10 @@ public Integer call() throws IOException {
513515
}
514516
}
515517

518+
private List<Path> convertToPaths(final List<String> pathsStr) {
519+
return pathsStr != null ? pathsStr.stream().map(Path::of).toList() : List.of();
520+
}
521+
516522
/**
517523
* Performs a resetting of the logging settings because they're wildly different if we do
518524
* structured logging.

framework/codemodder-base/src/main/java/io/codemodder/CodemodLoader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public CodemodLoader(
2828
final List<Path> includedFiles,
2929
final Map<String, List<RuleSarif>> ruleSarifByTool,
3030
final List<ParameterArgument> codemodParameters,
31-
final Path sonarIssuesJsonFile,
31+
final List<Path> sonarIssuesJsonFiles,
3232
final Path defectDojoFindingsJsonFile,
3333
final Path contrastVulnerabilitiesXmlFilePath) {
3434

@@ -100,7 +100,7 @@ public CodemodLoader(
100100
pathExcludes,
101101
orderedCodemodTypes,
102102
allWantedSarifs,
103-
sonarIssuesJsonFile,
103+
sonarIssuesJsonFiles,
104104
defectDojoFindingsJsonFile,
105105
contrastVulnerabilitiesXmlFilePath);
106106
allModules.addAll(modules);

framework/codemodder-base/src/main/java/io/codemodder/CodemodProvider.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ public interface CodemodProvider {
2222
* their own analysis)
2323
* @param codemodTypes the codemod types that are being run
2424
* @param sarifs the SARIF output of tools that are being run
25-
* @param sonarIssuesJsonPath the path to a Sonar issues JSON file retrieved from their web API --
26-
* may be null
25+
* @param sonarIssuesJsonPaths the path to a Sonar issues JSON file retrieved from their web API
26+
* -- may be null
2727
* @param contrastFindingsJsonPath the path to a Contrast findings JSON file retrieved from their
2828
* web API -- may be null
2929
* @return a set of modules that perform dependency injection
@@ -35,14 +35,14 @@ Set<AbstractModule> getModules(
3535
List<String> pathExcludes,
3636
List<Class<? extends CodeChanger>> codemodTypes,
3737
List<RuleSarif> sarifs,
38-
Path sonarIssuesJsonPath,
38+
List<Path> sonarIssuesJsonPaths,
3939
Path defectDojoFindingsJsonPath,
4040
Path contrastFindingsJsonPath);
4141

4242
/**
4343
* Tools this provider is interested in processing the SARIF output of. Codemodder CLI will look
4444
* for the SARIF outputted by tools in this list in the repository root and then provide the
45-
* results to {@link #getModules(Path, List, List, List, List, List, Path, Path, Path)} as a
45+
* results to {@link #getModules(Path, List, List, List, List, List, List, Path, Path)} as a
4646
* {@link List} of {@link RuleSarif}s.
4747
*
4848
* <p>By default, this returns an empty list.

framework/codemodder-testutils/src/main/java/io/codemodder/testutils/CodemodTestMixin.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.nio.file.StandardCopyOption;
1818
import java.util.*;
1919
import java.util.function.Function;
20+
import java.util.stream.Collectors;
2021
import java.util.stream.Stream;
2122
import org.junit.jupiter.api.DynamicTest;
2223
import org.junit.jupiter.api.TestFactory;
@@ -76,7 +77,8 @@ default Stream<DynamicTest> generateTestCases(@TempDir final Path tmpDir) throws
7677
projectProviders,
7778
metadata.doRetransformTest(),
7879
metadata.expectingFixesAtLines(),
79-
metadata.expectingFailedFixesAtLines());
80+
metadata.expectingFailedFixesAtLines(),
81+
metadata.sonarIssuesJsonFiles());
8082

8183
return DynamicTest.stream(inputStream, displayNameGenerator, testExecutor);
8284
}
@@ -91,7 +93,8 @@ private void verifyCodemod(
9193
final List<ProjectProvider> projectProviders,
9294
final boolean doRetransformTest,
9395
final int[] expectedFixLines,
94-
final int[] expectingFailedFixesAtLines)
96+
final int[] expectingFailedFixesAtLines,
97+
final String[] sonarIssuesJsonFiles)
9598
throws IOException {
9699

97100
// create a copy of the test file in the temp directory to serve as our "repository"
@@ -111,8 +114,21 @@ private void verifyCodemod(
111114
pathToJavaFile = newPathToJavaFile;
112115
}
113116

114-
// add the sonar JSON if one exists
115-
Path sonarJson = testResourceDir.resolve("sonar-issues.json");
117+
final List<String> sonarJsons =
118+
sonarIssuesJsonFiles != null ? Arrays.asList(sonarIssuesJsonFiles) : new ArrayList<>();
119+
120+
final List<Path> sonarJsonsPaths =
121+
sonarJsons.stream()
122+
.map(testResourceDir::resolve)
123+
.filter(Files::exists)
124+
.collect(Collectors.toList());
125+
126+
if (sonarJsonsPaths.isEmpty()) {
127+
Path defaultPath = testResourceDir.resolve("sonar-issues.json");
128+
if (Files.exists(defaultPath)) {
129+
sonarJsonsPaths.add(defaultPath);
130+
}
131+
}
116132

117133
// Check for any sarif files and build the RuleSarif map
118134
CodeDirectory codeDir = CodeDirectory.from(tmpDir);
@@ -139,7 +155,7 @@ private void verifyCodemod(
139155
List.of(pathToJavaFile),
140156
map,
141157
List.of(),
142-
Files.exists(sonarJson) ? sonarJson : null,
158+
sonarJsonsPaths,
143159
Files.exists(defectDojo) ? defectDojo : null,
144160
Files.exists(contrastXml) ? contrastXml : null);
145161

framework/codemodder-testutils/src/main/java/io/codemodder/testutils/Metadata.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,7 @@
4848

4949
/** The expected failed fix metadata that the codemod should report. */
5050
int[] expectingFailedFixesAtLines() default {};
51+
52+
/** Sonar issues file names for testing multiple json files */
53+
String[] sonarIssuesJsonFiles() default {};
5154
}

plugins/codemodder-plugin-appscan/src/main/java/io/codemodder/providers/sarif/appscan/AppScanProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public Set<AbstractModule> getModules(
1919
final List<String> excludePaths,
2020
final List<Class<? extends CodeChanger>> codemodTypes,
2121
final List<RuleSarif> sarifs,
22-
final Path sonarIssuesJsonFile,
22+
final List<Path> sonarIssuesJsonPaths,
2323
final Path defectDojoFindingsJsonFile,
2424
final Path contrastFindingsJsonPath) {
2525
return Set.of(new AppScanModule(codemodTypes, sarifs));

plugins/codemodder-plugin-aws/src/main/java/io/codemodder/plugins/aws/AwsProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public Set<AbstractModule> getModules(
1919
final List<String> excludePaths,
2020
final List<Class<? extends CodeChanger>> codemodTypes,
2121
final List<RuleSarif> sarifs,
22-
final Path sonarIssuesJsonFile,
22+
final List<Path> sonarIssuesJsonPaths,
2323
final Path defectDojoFindingsJsonFile,
2424
final Path contrastFindingsJsonPath) {
2525
return Set.of(new AwsClientModule());

0 commit comments

Comments
 (0)