Skip to content

Commit

Permalink
fix: fixes the crash for the deps with no versions and removes duplic…
Browse files Browse the repository at this point in the history
…ates (#105)

Fixes the crash for the dependencies with no versions and removes the
duplicates of the dependencies with different versions.
Jira: [APPENG-2442](https://issues.redhat.com/browse/APPENG-2442)

## Description

> Describe what you did and why.

**Related issue (if any):** fixes #issue_number_goes_here

## Checklist

- [x] I have followed this repository's contributing guidelines.
- [x] I will adhere to the project's code of conduct.

Signed-off-by: Olga Lavtar <[email protected]>
  • Loading branch information
olavtar authored May 2, 2024
1 parent 60e8c45 commit 05b9cb6
Show file tree
Hide file tree
Showing 16 changed files with 725 additions and 18 deletions.
95 changes: 78 additions & 17 deletions src/main/java/com/redhat/exhort/providers/GradleProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -86,7 +87,7 @@ private List<String> getIgnoredDeps(Path manifestPath) throws IOException {
// Process each ignored dependency
for (String dependency : ignoredLines) {
String ignoredDepInfo;
if (isNotation(dependency)) {
if (depHasLibsNotation(dependency)) {
ignoredDepInfo = getDepFromNotation(dependency, manifestPath);
} else {
ignoredDepInfo = getDepInfo(dependency);
Expand Down Expand Up @@ -184,17 +185,11 @@ public PackageURL toPurl(String groupId, String artifactId, String version) {
}
}

public static boolean isNotation(String line) {
int colonCount = 0;
for (char c : line.toCharArray()) {
if (c == ':') {
colonCount++;
if (colonCount > 1) {
return false; // Likely full dependency with group and artifact
}
}
}
return true; // Potentially a notation
private boolean depHasLibsNotation(String depToBeIgnored) {
Pattern pattern = Pattern.compile(":");
Matcher matcher = pattern.matcher(depToBeIgnored.trim());
return (depToBeIgnored.trim().startsWith("library(") || depToBeIgnored.trim().contains("libs."))
&& (matcher.results().count() <= 1);
}

private boolean isIgnoredLine(String line) {
Expand All @@ -216,7 +211,7 @@ private String extractPackageName(String line) {
return packageName;
}

private static Path getDependencies(Path manifestPath) throws IOException {
private Path getDependencies(Path manifestPath) throws IOException {
// check for custom gradle executable
var gradle = Operations.getCustomPathOrElse("gradle");
// create a temp file for storing the dependency tree in
Expand Down Expand Up @@ -254,21 +249,87 @@ private Sbom buildSbomFromTextFormat(
var rootPurl = parseDep(root);
sbom.addRoot(rootPurl);
List<String> lines = extractLines(textFormatFile, configName);
String[] array = new String[lines.size()];
for (int index = 0; index < array.length; index++) {
String line = lines.get(index);
List<String> arrayForSbom = new ArrayList<>();

for (String line : lines) {
line = line.replaceAll("---", "-").replaceAll(" ", " ");
line = line.replaceAll(":(.*):(.*) -> (.*)$", ":$1:$3");
line = line.replaceAll("(.*):(.*):(.*)$", "$1:$2:jar:$3");
line = line.replaceAll(" \\(n\\)$", "");
line = line.replaceAll(" \\(\\*\\)", "");
line = line.replaceAll("$", ":compile");
array[index] = line;
if (containsVersion(line)) {
arrayForSbom.add(line);
}
}
// remove duplicates for component analysis
if (List.of("api", "implementation", "compile").contains(configName)) {
removeDuplicateIfExists(arrayForSbom, textFormatFile);
}

String[] array = arrayForSbom.toArray(new String[0]);
parseDependencyTree(root, 0, array, sbom);
return sbom;
}

private void removeDuplicateIfExists(List<String> arrayForSbom, Path theContent) {
Consumer<String> removeDuplicateFunction =
dependency -> {
try {
String content = Files.readString(theContent);
PackageURL depUrl = parseDep(dependency);
String depVersion = depUrl.getVersion().trim();
int indexOfDuplicate = -1;
int selfIndex = -1;

for (int i = 0; i < arrayForSbom.size(); i++) {
PackageURL dep = parseDep(arrayForSbom.get(i));
if (dep.getNamespace().equals(depUrl.getNamespace())
&& dep.getName().equals(depUrl.getName())) {
if (dep.getVersion().equals(depVersion)) {
selfIndex = i;
} else if (!dep.getVersion().equals(depVersion) && indexOfDuplicate == -1) {
indexOfDuplicate = i;
}
}
}

if (selfIndex != -1 && selfIndex != indexOfDuplicate && indexOfDuplicate != -1) {
PackageURL duplicateDepVersion = parseDep(arrayForSbom.get(indexOfDuplicate));
Pattern pattern =
Pattern.compile(
".*" + depVersion + "\\W?->\\W?" + duplicateDepVersion.getVersion() + ".*");
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
arrayForSbom.remove(selfIndex);
} else {
pattern =
Pattern.compile(
".*" + duplicateDepVersion.getVersion() + "\\W?->\\W?" + depVersion + ".*");
matcher = pattern.matcher(content);
if (matcher.find()) {
arrayForSbom.remove(indexOfDuplicate);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
};
List<String> copyOfArrayForSbom = new ArrayList<>(arrayForSbom);
copyOfArrayForSbom.forEach(removeDuplicateFunction);
}

private boolean containsVersion(String line) {
String lineStripped = line.replace("(n)", "").trim();
Pattern pattern1 =
Pattern.compile("\\W*[a-z0-9.-]+:[a-z0-9.-]+:[0-9]+[.][0-9]+(.[0-9]+)?(.*)?.*");
Pattern pattern2 = Pattern.compile(".*version:\\s?(')?[0-9]+[.][0-9]+(.[0-9]+)?(')?");
Matcher matcher1 = pattern1.matcher(lineStripped);
Matcher matcher2 = pattern2.matcher(lineStripped);
return (matcher1.find() || matcher2.find()) && !lineStripped.contains("libs.");
}

private String getRoot(Path textFormatFile, Map<String, String> propertiesMap)
throws IOException {
String group = propertiesMap.get("group");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ static Stream<String> testFolders() {
"deps_with_ignore_full_specification",
"deps_with_ignore_named_params",
"deps_with_ignore_notations",
"deps_with_no_ignore_common_paths");
"deps_with_no_ignore_common_paths",
"deps_with_duplicate_no_version",
"deps_with_duplicate_different_versions");
}

@ParameterizedTest
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
plugins {
id 'java'
}

group = 'org.acme.dbaas'
version = '1.0.0-SNAPSHOT'

repositories {
mavenCentral()
}

dependencies {
implementation "log4j:log4j:1.2.17"
implementation "log4j:log4j:1.2.14"
}
test {
useJUnitPlatform()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

> Task :dependencies

------------------------------------------------------------
Root project 'postgresql-orm-quarkus'
------------------------------------------------------------

annotationProcessor - Annotation processors and their dependencies for source set 'main'.
No dependencies

compileClasspath - Compile classpath for source set 'main'.
+--- log4j:log4j:1.2.17
\--- log4j:log4j:1.2.14 -> 1.2.17

compileOnly - Compile-only dependencies for the 'main' feature. (n)
No dependencies

default - Configuration for default artifacts. (n)
No dependencies

implementation - Implementation dependencies for the 'main' feature. (n)
+--- log4j:log4j:1.2.17 (n)
\--- log4j:log4j:1.2.14 (n)

mainSourceElements - List of source directories contained in the Main SourceSet. (n)
No dependencies

runtimeClasspath - Runtime classpath of source set 'main'.
+--- log4j:log4j:1.2.17
\--- log4j:log4j:1.2.14 -> 1.2.17

runtimeElements - Runtime elements for the 'main' feature. (n)
No dependencies

runtimeOnly - Runtime-only dependencies for the 'main' feature. (n)
No dependencies

testAnnotationProcessor - Annotation processors and their dependencies for source set 'test'.
No dependencies

testCompileClasspath - Compile classpath for source set 'test'.
+--- log4j:log4j:1.2.17
\--- log4j:log4j:1.2.14 -> 1.2.17

testCompileOnly - Compile only dependencies for source set 'test'. (n)
No dependencies

testImplementation - Implementation only dependencies for source set 'test'. (n)
No dependencies

testRuntimeClasspath - Runtime classpath of source set 'test'.
+--- log4j:log4j:1.2.17
\--- log4j:log4j:1.2.14 -> 1.2.17

testRuntimeOnly - Runtime only dependencies for source set 'test'. (n)
No dependencies

(*) - Indicates repeated occurrences of a transitive dependency subtree. Gradle expands transitive dependency subtrees only once per project; repeat occurrences only display the root of the subtree, followed by this annotation.

(n) - A dependency or dependency configuration that cannot be resolved.

A web-based, searchable dependency report is available by adding the --scan option.

BUILD SUCCESSFUL in 375ms
1 actionable task: 1 executed
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"bomFormat" : "CycloneDX",
"specVersion" : "1.4",
"version" : 1,
"metadata" : {
"timestamp" : "2024-05-02T05:04:32Z",
"component" : {
"group" : "org.acme.dbaas",
"name" : "postgresql-orm-quarkus",
"version" : "1.0.0-SNAPSHOT",
"purl" : "pkg:maven/org.acme.dbaas/[email protected]",
"type" : "application",
"bom-ref" : "pkg:maven/org.acme.dbaas/[email protected]"
}
},
"components" : [
{
"group" : "org.acme.dbaas",
"name" : "postgresql-orm-quarkus",
"version" : "1.0.0-SNAPSHOT",
"purl" : "pkg:maven/org.acme.dbaas/[email protected]",
"type" : "application",
"bom-ref" : "pkg:maven/org.acme.dbaas/[email protected]"
},
{
"group" : "log4j",
"name" : "log4j",
"version" : "1.2.17",
"purl" : "pkg:maven/log4j/[email protected]",
"type" : "library",
"bom-ref" : "pkg:maven/log4j/[email protected]"
}
],
"dependencies" : [
{
"ref" : "pkg:maven/org.acme.dbaas/[email protected]",
"dependsOn" : [
"pkg:maven/log4j/[email protected]"
]
},
{
"ref" : "pkg:maven/log4j/[email protected]",
"dependsOn" : [ ]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"bomFormat" : "CycloneDX",
"specVersion" : "1.4",
"version" : 1,
"metadata" : {
"timestamp" : "2024-05-01T22:57:54Z",
"component" : {
"group" : "org.acme.dbaas",
"name" : "postgresql-orm-quarkus",
"version" : "1.0.0-SNAPSHOT",
"purl" : "pkg:maven/org.acme.dbaas/[email protected]",
"type" : "application",
"bom-ref" : "pkg:maven/org.acme.dbaas/[email protected]"
}
},
"components" : [
{
"group" : "org.acme.dbaas",
"name" : "postgresql-orm-quarkus",
"version" : "1.0.0-SNAPSHOT",
"purl" : "pkg:maven/org.acme.dbaas/[email protected]",
"type" : "application",
"bom-ref" : "pkg:maven/org.acme.dbaas/[email protected]"
},
{
"group" : "log4j",
"name" : "log4j",
"version" : "1.2.17",
"purl" : "pkg:maven/log4j/[email protected]",
"type" : "library",
"bom-ref" : "pkg:maven/log4j/[email protected]"
}
],
"dependencies" : [
{
"ref" : "pkg:maven/org.acme.dbaas/[email protected]",
"dependsOn" : [
"pkg:maven/log4j/[email protected]"
]
},
{
"ref" : "pkg:maven/log4j/[email protected]",
"dependsOn" : [ ]
}
]
}
Loading

0 comments on commit 05b9cb6

Please sign in to comment.