diff options
author | Havoc Pennington <hp@pobox.com> | 2025-03-22 02:47:45 -0400 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2025-03-26 20:03:12 +0000 |
commit | 2a843ab0326b7ba3d9f1d27e9487d77b0cdfcb06 (patch) | |
tree | f4fb4cdf9aab4eda26b703014d6bd00cba454131 /server/sonar-db-dao/src | |
parent | a97c92eeb5a41e1c6b5035c92e0ab5f89ae6ede2 (diff) | |
download | sonarqube-2a843ab0326b7ba3d9f1d27e9487d77b0cdfcb06.tar.gz sonarqube-2a843ab0326b7ba3d9f1d27e9487d77b0cdfcb06.zip |
SCA-182: core-extension-sca: move all sca db classes to sca-application
Diffstat (limited to 'server/sonar-db-dao/src')
70 files changed, 45 insertions, 6342 deletions
diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java index 7f3905764e1..589145c220f 100644 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java +++ b/server/sonar-db-dao/src/it/java/org/sonar/db/purge/PurgeDaoIT.java @@ -29,7 +29,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Random; import java.util.Set; @@ -89,10 +91,6 @@ import org.sonar.db.property.PropertyDto; import org.sonar.db.report.ReportScheduleDto; import org.sonar.db.report.ReportSubscriptionDto; import org.sonar.db.rule.RuleDto; -import org.sonar.db.sca.ScaDependenciesDbTester; -import org.sonar.db.sca.ScaIssueReleaseDto; -import org.sonar.db.sca.ScaReleasesDbTester; -import org.sonar.db.sca.ScaSeverity; import org.sonar.db.source.FileSourceDto; import org.sonar.db.user.UserDismissedMessageDto; import org.sonar.db.user.UserDto; @@ -140,6 +138,7 @@ class PurgeDaoIT { private final LogTesterJUnit5 logTester = new LogTesterJUnit5(); private final DbClient dbClient = db.getDbClient(); private final DbSession dbSession = db.getSession(); + private final PurgeDao underTest = db.getDbClient().purgeDao(); @Test @@ -1964,38 +1963,57 @@ oldCreationDate)); } + private <K, V> Map<K, V> merge(Map<? extends K, ? extends V> map1, Map<? extends K, ? extends V> map2) { + Map<K, V> result = new HashMap<>(map1); + result.putAll(map2); + return result; + } + + // the SCA mappers are in an extension, so we have to use direct sql here. + // A cleaner approach would be to allow extensions to add purge logic on branch + // deletion and remove SCA knowledge from the core PurgeMapper. + private void insertScaData(String branch1Uuid, String branch2Uuid) { + var releaseBase = Map.of("package_url", "purl1", + "package_manager", "MAVEN", + "package_name", "whatever", + "version", "1.0", + "license_expression", "MIT", + "known", true, + "created_at", 0L, "updated_at", 0L); + db.executeInsert("sca_releases", merge(releaseBase, Map.of("uuid", "release-uuid1", "component_uuid", branch1Uuid))); + db.executeInsert("sca_releases", merge(releaseBase, Map.of("uuid", "release-uuid2", "component_uuid", branch2Uuid))); + assertThat(db.countRowsOfTable(dbSession, "sca_releases")).isEqualTo(2); + + var dependencyBase = Map.of("created_at", 0L, "updated_at", 0L, + "direct", true, "scope", "compile", "new_in_pull_request", true); + db.executeInsert("sca_dependencies", merge(dependencyBase, Map.of("uuid", "dependency-uuid1", "sca_release_uuid", "release-uuid1"))); + db.executeInsert("sca_dependencies", merge(dependencyBase, Map.of("uuid", "dependency-uuid2", "sca_release_uuid", "release-uuid2"))); + assertThat(db.countRowsOfTable(dbSession, "sca_dependencies")).isEqualTo(2); + + // the issue uuids here don't even exist but doesn't matter, we don't delete issues so not testing that + var issueReleaseBase = Map.of("created_at", 0L, "updated_at", 0L, + "severity", "INFO", "severity_sort_key", 42); + db.executeInsert("sca_issues_releases", merge(issueReleaseBase, Map.of("uuid", "issue-release-uuid1", + "sca_issue_uuid", "issue-uuid1", "sca_release_uuid", "release-uuid1"))); + db.executeInsert("sca_issues_releases", merge(issueReleaseBase, Map.of("uuid", "issue-release-uuid2", + "sca_issue_uuid", "issue-uuid2", "sca_release_uuid", "release-uuid2"))); + + assertThat(db.countRowsOfTable(dbSession, "sca_issues_releases")).isEqualTo(2); + } + @Test void deleteBranch_purgesScaActivity() { ProjectDto project = db.components().insertPublicProject().getProjectDto(); BranchDto branch1 = db.components().insertProjectBranch(project); BranchDto branch2 = db.components().insertProjectBranch(project); - ScaReleasesDbTester scaReleasesDbTester = new ScaReleasesDbTester(db); - var release1 = scaReleasesDbTester.insertScaRelease(branch1.getUuid(), "1"); - var release2 = scaReleasesDbTester.insertScaRelease(branch2.getUuid(), "2"); - - ScaDependenciesDbTester scaDependenciesDbTester = new ScaDependenciesDbTester(db); - scaDependenciesDbTester.insertScaDependency(release1.uuid(), "1"); - scaDependenciesDbTester.insertScaDependency(release2.uuid(), "2"); - - ScaIssueReleaseDto issueRelease1 = new ScaIssueReleaseDto.Builder().setUuid("foo1").setScaIssueUuid("baz").setSeverity(ScaSeverity.LOW).setScaReleaseUuid(release1.uuid()).build(); - ScaIssueReleaseDto issueRelease2 = new ScaIssueReleaseDto.Builder().setUuid("foo2").setScaIssueUuid("baz").setSeverity(ScaSeverity.LOW).setScaReleaseUuid(release2.uuid()).build(); - dbClient.scaIssuesReleasesDao().insert(dbSession, issueRelease1); - dbClient.scaIssuesReleasesDao().insert(dbSession, issueRelease2); - - assertThat(dbClient.scaReleasesDao().selectByBranchUuid(dbSession, branch1.getUuid())).isNotEmpty(); - assertThat(dbClient.scaDependenciesDao().selectByBranchUuid(dbSession, branch1.getUuid())).isNotEmpty(); - assertThat(dbClient.scaIssuesReleasesDao().selectByBranchUuid(dbSession, branch1.getUuid())).isNotEmpty(); + insertScaData(branch1.getUuid(), branch2.getUuid()); underTest.deleteBranch(dbSession, branch1.getUuid()); - assertThat(dbClient.scaReleasesDao().selectByBranchUuid(dbSession, branch1.getUuid())).isEmpty(); - assertThat(dbClient.scaDependenciesDao().selectByBranchUuid(dbSession, branch1.getUuid())).isEmpty(); - assertThat(dbClient.scaIssuesReleasesDao().selectByBranchUuid(dbSession, branch1.getUuid())).isEmpty(); - - assertThat(dbClient.scaReleasesDao().selectByBranchUuid(dbSession, branch2.getUuid())).isNotEmpty(); - assertThat(dbClient.scaDependenciesDao().selectByBranchUuid(dbSession, branch2.getUuid())).isNotEmpty(); - assertThat(dbClient.scaIssuesReleasesDao().selectByBranchUuid(dbSession, branch2.getUuid())).isNotEmpty(); + assertThat(db.countRowsOfTable(dbSession, "sca_releases")).isEqualTo(1); + assertThat(db.countRowsOfTable(dbSession, "sca_dependencies")).isEqualTo(1); + assertThat(db.countRowsOfTable(dbSession, "sca_issues_releases")).isEqualTo(1); } private AnticipatedTransitionDto getAnticipatedTransitionsDto(String uuid, String projectUuid, Date creationDate) { diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaDependenciesDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaDependenciesDaoIT.java deleted file mode 100644 index 99c028718ef..00000000000 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaDependenciesDaoIT.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; -import org.sonar.db.Pagination; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ProjectData; - -import static org.assertj.core.api.Assertions.assertThat; - -class ScaDependenciesDaoIT { - - @RegisterExtension - private final DbTester db = DbTester.create(System2.INSTANCE); - - private final ScaDependenciesDao scaDependenciesDao = db.getDbClient().scaDependenciesDao(); - - @Test - void insert_shouldPersistScaDependencies() { - ScaDependencyDto scaDependencyDto = db.getScaDependenciesDbTester().insertScaDependency("scaReleaseUuid", "1"); - - List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_dependencies"); - assertThat(select).hasSize(1); - Map<String, Object> stringObjectMap = select.get(0); - assertThat(stringObjectMap).containsExactlyInAnyOrderEntriesOf( - Map.ofEntries( - Map.entry("uuid", scaDependencyDto.uuid()), - Map.entry("sca_release_uuid", scaDependencyDto.scaReleaseUuid()), - Map.entry("direct", scaDependencyDto.direct()), - Map.entry("scope", scaDependencyDto.scope()), - Map.entry("user_dependency_file_path", scaDependencyDto.userDependencyFilePath()), - Map.entry("lockfile_dependency_file_path", scaDependencyDto.lockfileDependencyFilePath()), - Map.entry("chains", scaDependencyDto.getChainsJson()), - Map.entry("new_in_pull_request", scaDependencyDto.newInPullRequest()), - Map.entry("production_scope", scaDependencyDto.productionScope()), - Map.entry("created_at", scaDependencyDto.createdAt()), - Map.entry("updated_at", scaDependencyDto.updatedAt()))); - } - - @Test - void deleteByUuid_shouldDeleteScaDependencies() { - ScaDependencyDto scaDependencyDto = db.getScaDependenciesDbTester().insertScaDependency("scaReleaseUuid", "1"); - - List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_dependencies"); - assertThat(select).isNotEmpty(); - - scaDependenciesDao.deleteByUuid(db.getSession(), scaDependencyDto.uuid()); - - select = db.select(db.getSession(), "select * from sca_dependencies"); - assertThat(select).isEmpty(); - } - - @Test - void selectByUuid_shouldLoadScaDependency() { - ScaDependencyDto scaDependencyDto = db.getScaDependenciesDbTester().insertScaDependency("scaReleaseUuid", "1"); - - var loadedOptional = scaDependenciesDao.selectByUuid(db.getSession(), scaDependencyDto.uuid()); - - assertThat(loadedOptional).contains(scaDependencyDto); - } - - @Test - void selectByReleaseUuids_shouldReturnScaDependencies() { - ComponentDto componentDto = prepareComponentDto(); - ScaDependencyDto scaDependencyDto1a = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1a", true, PackageManager.MAVEN, "foo.bar1"); - // same release, different dependency - ScaDependencyDto scaDependencyDto1b = db.getScaDependenciesDbTester().insertScaDependency(scaDependencyDto1a.scaReleaseUuid(), "1b", false); - ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "2", true, PackageManager.MAVEN, "foo.bar2"); - ScaDependencyDto scaDependencyDto3 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "3", true, PackageManager.MAVEN, "foo.bar3"); - - List<ScaDependencyDto> results = scaDependenciesDao.selectByReleaseUuids(db.getSession(), List.of(scaDependencyDto1a.scaReleaseUuid(), scaDependencyDto2.scaReleaseUuid())); - - assertThat(results) - .containsExactlyInAnyOrder(scaDependencyDto1a, scaDependencyDto1b, scaDependencyDto2) - .doesNotContain(scaDependencyDto3); - } - - @Test - void selectByQuery_shouldReturnScaDependencies_whenQueryByBranchUuid() { - ComponentDto componentDto = prepareComponentDto(); - ScaDependencyDto scaDependencyDto1 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1", true, PackageManager.MAVEN, "foo.bar"); - // same release, different dependency - ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependency(scaDependencyDto1.scaReleaseUuid(), "2", false); - - ScaDependenciesQuery scaDependenciesQuery = new ScaDependenciesQuery(componentDto.branchUuid(), null, null, null); - List<ScaDependencyDto> results = scaDependenciesDao.selectByQuery(db.getSession(), scaDependenciesQuery, Pagination.all()); - - assertThat(results).containsExactlyInAnyOrder(scaDependencyDto1, scaDependencyDto2); - } - - @Test - void selectByQuery_shouldReturnPaginatedScaDependencies() { - ComponentDto componentDto = prepareComponentDto(); - ScaDependencyDto scaDependencyDto1 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1", true, PackageManager.MAVEN, "foo.bar"); - ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "2", true, PackageManager.MAVEN, "foo.bar"); - ScaDependencyDto scaDependencyDto3 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "3", true, PackageManager.MAVEN, "something"); - ScaDependencyDto scaDependencyDto4 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "4", true, PackageManager.MAVEN, "something-else"); - - ScaDependenciesQuery scaDependenciesQuery = new ScaDependenciesQuery(componentDto.branchUuid(), null, null, null); - List<ScaDependencyDto> page1Results = scaDependenciesDao.selectByQuery(db.getSession(), scaDependenciesQuery, Pagination.forPage(1).andSize(2)); - List<ScaDependencyDto> page2Results = scaDependenciesDao.selectByQuery(db.getSession(), scaDependenciesQuery, Pagination.forPage(2).andSize(2)); - - // we order by uuid, so order is not meaningful here - var allResults = new ArrayList<>(page1Results); - allResults.addAll(page2Results); - assertThat(allResults).containsExactlyInAnyOrder(scaDependencyDto1, scaDependencyDto2, scaDependencyDto3, scaDependencyDto4); - assertThat(List.of(page1Results.size(), page2Results.size())).containsExactly(2, 2); - } - - @Test - void selectByQuery_shouldPartiallyMatchPackageName_whenQueriedByText() { - ComponentDto componentDto = prepareComponentDto(); - ScaDependencyDto scaDependencyDto1 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1", true, PackageManager.MAVEN, "foo.bar"); - @SuppressWarnings("unused") - ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "2", true, PackageManager.MAVEN, "bar.mee"); - ScaDependencyDto scaDependencyDto3 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "3", true, PackageManager.MAVEN, "foo.bar.me"); - @SuppressWarnings("unused") - ScaDependencyDto scaDependencyDto4 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "4", true, PackageManager.MAVEN, "some.foo.bar"); - - ScaDependenciesQuery scaDependenciesQuery = new ScaDependenciesQuery(componentDto.branchUuid(), null, null, "foo.bar"); - List<ScaDependencyDto> results = scaDependenciesDao.selectByQuery(db.getSession(), scaDependenciesQuery, Pagination.all()); - - assertThat(results).hasSize(2); - assertThat(results.get(0)).usingRecursiveComparison().isEqualTo(scaDependencyDto1); - assertThat(results.get(1)).usingRecursiveComparison().isEqualTo(scaDependencyDto3); - - ScaDependenciesQuery scaDependenciesCaseInsensitiveQuery = new ScaDependenciesQuery(componentDto.branchUuid(), null, null, "Foo.Bar"); - List<ScaDependencyDto> resultsCaseInsensitive = scaDependenciesDao.selectByQuery(db.getSession(), scaDependenciesCaseInsensitiveQuery, Pagination.all()); - - assertThat(resultsCaseInsensitive).hasSize(2); - assertThat(resultsCaseInsensitive.get(0)).usingRecursiveComparison().isEqualTo(scaDependencyDto1); - assertThat(resultsCaseInsensitive.get(1)).usingRecursiveComparison().isEqualTo(scaDependencyDto3); - } - - @Test - void selectByQuery_shouldReturnScaDependencies_whenQueryByDirect() { - ComponentDto componentDto = prepareComponentDto(); - ScaDependencyDto scaDependencyDto1 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1", true, PackageManager.MAVEN, "foo.bar"); - ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "2", false, PackageManager.MAVEN, "foo.bar"); - - ScaDependenciesQuery scaDependenciesDirectQuery = new ScaDependenciesQuery(componentDto.branchUuid(), true, null, null); - List<ScaDependencyDto> resultsDirect = scaDependenciesDao.selectByQuery(db.getSession(), scaDependenciesDirectQuery, Pagination.all()); - - assertThat(resultsDirect).hasSize(1); - assertThat(resultsDirect.get(0)).usingRecursiveComparison().isEqualTo(scaDependencyDto1); - - ScaDependenciesQuery scaDependenciesNoDirectQuery = new ScaDependenciesQuery(componentDto.branchUuid(), false, null, null); - List<ScaDependencyDto> resultsNoDirect = scaDependenciesDao.selectByQuery(db.getSession(), scaDependenciesNoDirectQuery, Pagination.all()); - - assertThat(resultsNoDirect).hasSize(1); - assertThat(resultsNoDirect.get(0)).usingRecursiveComparison().isEqualTo(scaDependencyDto2); - } - - @Test - void selectByQuery_shouldReturnScaDependencies_whenQueryByPackageManager() { - ComponentDto componentDto = prepareComponentDto(); - ScaDependencyDto scaDependencyDto1 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1", true, PackageManager.MAVEN, "foo.bar"); - ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "2", true, PackageManager.NPM, "foo.bar"); - ScaDependencyDto scaDependencyDto3 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "3", true, PackageManager.CARGO, "foo.bar"); - - ScaDependenciesQuery scaDependenciesMavenQuery = new ScaDependenciesQuery(componentDto.branchUuid(), null, List.of(PackageManager.MAVEN.name()), null); - List<ScaDependencyDto> resultsMaven = scaDependenciesDao.selectByQuery(db.getSession(), scaDependenciesMavenQuery, Pagination.all()); - - assertThat(resultsMaven).hasSize(1); - assertThat(resultsMaven.get(0)).usingRecursiveComparison().isEqualTo(scaDependencyDto1); - - ScaDependenciesQuery scaDependenciesNpmAndCargoQuery = new ScaDependenciesQuery(componentDto.branchUuid(), null, - List.of(PackageManager.NPM.name(), PackageManager.CARGO.name()), null); - List<ScaDependencyDto> resultsNpm = scaDependenciesDao.selectByQuery(db.getSession(), scaDependenciesNpmAndCargoQuery, Pagination.all()); - - assertThat(resultsNpm).hasSize(2); - assertThat(resultsNpm.get(0)).usingRecursiveComparison().isEqualTo(scaDependencyDto2); - assertThat(resultsNpm.get(1)).usingRecursiveComparison().isEqualTo(scaDependencyDto3); - } - - @Test - void update_shouldUpdateScaDependency() { - ScaDependencyDto scaDependencyDto = db.getScaDependenciesDbTester().insertScaDependency("scaReleaseUuid", "1", true); - ScaDependencyDto updatedScaDependency = scaDependencyDto.toBuilder() - .setUpdatedAt(scaDependencyDto.updatedAt() + 1) - .setDirect(!scaDependencyDto.direct()) - .setLockfileDependencyFilePath("lockfile2") - .setProductionScope(!scaDependencyDto.productionScope()) - .build(); - - scaDependenciesDao.update(db.getSession(), updatedScaDependency); - - List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_dependencies"); - assertThat(select).hasSize(1); - Map<String, Object> stringObjectMap = select.get(0); - assertThat(stringObjectMap).containsExactlyInAnyOrderEntriesOf( - Map.ofEntries( - Map.entry("uuid", updatedScaDependency.uuid()), - Map.entry("sca_release_uuid", updatedScaDependency.scaReleaseUuid()), - Map.entry("direct", updatedScaDependency.direct()), - Map.entry("scope", updatedScaDependency.scope()), - Map.entry("user_dependency_file_path", updatedScaDependency.userDependencyFilePath()), - Map.entry("lockfile_dependency_file_path", updatedScaDependency.lockfileDependencyFilePath()), - Map.entry("chains", updatedScaDependency.getChainsJson()), - Map.entry("new_in_pull_request", updatedScaDependency.newInPullRequest()), - Map.entry("production_scope", updatedScaDependency.productionScope()), - Map.entry("created_at", updatedScaDependency.createdAt()), - Map.entry("updated_at", updatedScaDependency.updatedAt()))); - } - - @Test - void countByQuery_shouldReturnTheTotalOfDependencies() { - ComponentDto componentDto1 = prepareComponentDto(); - db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto1.uuid(), "1", true, PackageManager.MAVEN, "foo.bar"); - db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto1.uuid(), "2", true, PackageManager.MAVEN, "foo.bar.mee"); - db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto1.uuid(), "3", true, PackageManager.MAVEN, "bar.foo"); - - ScaDependenciesQuery scaDependenciesQuery = new ScaDependenciesQuery(componentDto1.branchUuid(), null, null, "foo"); - - assertThat(scaDependenciesDao.countByQuery(db.getSession(), scaDependenciesQuery)).isEqualTo(2); - assertThat(scaDependenciesDao.countByQuery(db.getSession(), new ScaDependenciesQuery(componentDto1.branchUuid(), null, null, null))).isEqualTo(3); - assertThat(scaDependenciesDao.countByQuery(db.getSession(), new ScaDependenciesQuery("another_branch_uuid", null, null, null))).isZero(); - } - - private ComponentDto prepareComponentDto() { - ProjectData projectData = db.components().insertPublicProject(); - return projectData.getMainBranchComponent(); - } -} diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaIssuesDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaIssuesDaoIT.java deleted file mode 100644 index a13fa082603..00000000000 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaIssuesDaoIT.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import java.util.Map; -import org.apache.ibatis.exceptions.PersistenceException; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -class ScaIssuesDaoIT { - - @RegisterExtension - private final DbTester db = DbTester.create(System2.INSTANCE); - - private final ScaIssuesDao scaIssuesDao = db.getDbClient().scaIssuesDao(); - - private static final ScaIssueDto newScaIssueDto(String suffix) { - return new ScaIssueDto("uuid" + suffix, ScaIssueType.PROHIBITED_LICENSE, "fakePackageUrl" + suffix, "fakeVulnerabilityId" + suffix, "fakeSpdxId" + suffix, 1L, 2L); - } - - @Test - void insert_shouldPersistScaIssues() { - ScaIssueDto issueDto = newScaIssueDto("1"); - scaIssuesDao.insert(db.getSession(), issueDto); - - List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_issues"); - assertThat(select).hasSize(1); - Map<String, Object> stringObjectMap = select.get(0); - assertThat(stringObjectMap).containsExactlyInAnyOrderEntriesOf( - Map.ofEntries( - Map.entry("uuid", issueDto.uuid()), - Map.entry("sca_issue_type", issueDto.scaIssueType().name()), - Map.entry("package_url", issueDto.packageUrl()), - Map.entry("vulnerability_id", issueDto.vulnerabilityId()), - Map.entry("spdx_license_id", issueDto.spdxLicenseId()), - Map.entry("created_at", issueDto.createdAt()), - Map.entry("updated_at", issueDto.updatedAt()))); - } - - // Postgresql apparently doesn't support doing anything else in the session - // after a statement with an error (constraint violation), while other - // databases do. So we use a dedicated session here. - private void insertAndCommit(ScaIssueDto issueDto) { - try (var dbSession = db.getDbClient().openSession(false)) { - scaIssuesDao.insert(dbSession, issueDto); - dbSession.commit(true); - } - } - - @Test - void insert_shouldFailOnDuplicateInsert() { - // we are avoiding db.getSession() in here because the constraint violation - // can invalidate the session and there's some chance of deadlock problems - // with multiple sessions so let's just juggle dedicated sessions manually - // for each query and not use the global session from DbTester - - ScaIssueDto issueDto = newScaIssueDto("1"); - try (var dbSession = db.getDbClient().openSession(false)) { - scaIssuesDao.insert(dbSession, issueDto); - dbSession.commit(); - } - - ScaIssueDto issueDtoDifferentUuid = new ScaIssueDto("uuid-different", issueDto.scaIssueType(), issueDto.packageUrl(), - issueDto.vulnerabilityId(), issueDto.spdxLicenseId(), 10L, 11L); - - assertThrows(PersistenceException.class, () -> insertAndCommit(issueDtoDifferentUuid)); - - try (var dbSession = db.getDbClient().openSession(false)) { - List<Map<String, Object>> select = db.select(dbSession, "select * from sca_issues"); - assertThat(select).hasSize(1); - Map<String, Object> stringObjectMap = select.get(0); - assertThat(stringObjectMap).containsEntry("uuid", issueDto.uuid()); - } - } - - @Test - void selectByUuid_shouldLoadScaIssue() { - ScaIssueDto issueDto = newScaIssueDto("1"); - scaIssuesDao.insert(db.getSession(), issueDto); - - var loadedOptional = scaIssuesDao.selectByUuid(db.getSession(), issueDto.uuid()); - - assertThat(loadedOptional).contains(issueDto); - } - - @Test - void selectByUuids_shouldLoadScaIssues() { - List<ScaIssueDto> issueDtos = List.of(newScaIssueDto("1"), newScaIssueDto("2"), newScaIssueDto("3")); - for (var issueDto : issueDtos) { - scaIssuesDao.insert(db.getSession(), issueDto); - } - - List<String> uuidsToLoad = List.of(issueDtos.get(0).uuid(), issueDtos.get(2).uuid()); - var loaded = scaIssuesDao.selectByUuids(db.getSession(), uuidsToLoad); - - assertThat(loaded).containsExactlyInAnyOrder(issueDtos.get(0), issueDtos.get(2)); - } - - @Test - void selectUuidByValue_shouldLoadScaIssue() { - List<ScaIssueDto> issueDtos = List.of(newScaIssueDto("1"), newScaIssueDto("2"), newScaIssueDto("3")); - for (var issueDto : issueDtos) { - scaIssuesDao.insert(db.getSession(), issueDto); - } - - ScaIssueDto toLoad = issueDtos.get(1); - var loadedOptionalUuid = scaIssuesDao.selectUuidByValue(db.getSession(), toLoad); - - assertThat(loadedOptionalUuid).contains(toLoad.uuid()); - } -} diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaIssuesReleasesDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaIssuesReleasesDaoIT.java deleted file mode 100644 index 8a4f5d4bec7..00000000000 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaIssuesReleasesDaoIT.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import java.util.Map; -import org.apache.ibatis.exceptions.PersistenceException; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertThrows; - -class ScaIssuesReleasesDaoIT { - - @RegisterExtension - private final DbTester db = DbTester.create(System2.INSTANCE); - - private final ScaIssuesReleasesDao scaIssuesReleasesDao = db.getDbClient().scaIssuesReleasesDao(); - - private static ScaIssueReleaseDto newScaIssueReleaseDto(String suffix) { - return new ScaIssueReleaseDto("uuid" + suffix, "sca-issue-uuid" + suffix, "sca-release-uuid" + suffix, ScaSeverity.INFO, 1L, 2L); - } - - @Test - void insert_shouldPersistScaIssuesReleases() { - ScaIssueReleaseDto issueReleaseDto = newScaIssueReleaseDto("1"); - - scaIssuesReleasesDao.insert(db.getSession(), issueReleaseDto); - - List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_issues_releases"); - assertThat(select).hasSize(1); - Map<String, Object> stringObjectMap = select.get(0); - assertThat(stringObjectMap).usingRecursiveComparison().isEqualTo( - Map.ofEntries( - Map.entry("uuid", issueReleaseDto.uuid()), - Map.entry("sca_issue_uuid", issueReleaseDto.scaIssueUuid()), - Map.entry("sca_release_uuid", issueReleaseDto.scaReleaseUuid()), - Map.entry("severity", issueReleaseDto.severity().name()), - Map.entry("severity_sort_key", (long) issueReleaseDto.severitySortKey()), - Map.entry("created_at", issueReleaseDto.createdAt()), - Map.entry("updated_at", issueReleaseDto.updatedAt()))); - } - - // Postgresql apparently doesn't support doing anything else in the session - // after a statement with an error (constraint violation), while other - // databases do. So we use a dedicated session here. - private void insertAndCommit(ScaIssueReleaseDto issueReleaseDto) { - try (var dbSession = db.getDbClient().openSession(false)) { - scaIssuesReleasesDao.insert(dbSession, issueReleaseDto); - dbSession.commit(true); - } - } - - @Test - void insert_shouldFailOnDuplicateInsert() { - ScaIssueReleaseDto issueReleaseDto = newScaIssueReleaseDto("1"); - try (var dbSession = db.getDbClient().openSession(false)) { - scaIssuesReleasesDao.insert(dbSession, issueReleaseDto); - dbSession.commit(); - } - - ScaIssueReleaseDto issueReleaseDtoDifferentUuid = new ScaIssueReleaseDto("uuid-different", - issueReleaseDto.scaIssueUuid(), issueReleaseDto.scaReleaseUuid(), ScaSeverity.INFO, - 10L, 11L); - - assertThrows(PersistenceException.class, () -> insertAndCommit(issueReleaseDtoDifferentUuid)); - - try (var dbSession = db.getDbClient().openSession(false)) { - List<Map<String, Object>> select = db.select(dbSession, "select * from sca_issues_releases"); - assertThat(select).hasSize(1); - Map<String, Object> stringObjectMap = select.get(0); - assertThat(stringObjectMap).containsEntry("uuid", issueReleaseDto.uuid()); - } - } - - @Test - void deleteByUuid_shouldDelete() { - var dbSession = db.getSession(); - ScaIssueReleaseDto issueReleaseDto = newScaIssueReleaseDto("1"); - scaIssuesReleasesDao.insert(dbSession, issueReleaseDto); - dbSession.commit(); - - assertThat(db.countRowsOfTable(dbSession, "sca_issues_releases")).isOne(); - - scaIssuesReleasesDao.deleteByUuid(dbSession, issueReleaseDto.uuid()); - - assertThat(db.countRowsOfTable(dbSession, "sca_issues_releases")).isZero(); - } -} diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaIssuesReleasesDetailsDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaIssuesReleasesDetailsDaoIT.java deleted file mode 100644 index 4db2590aed3..00000000000 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaIssuesReleasesDetailsDaoIT.java +++ /dev/null @@ -1,618 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import com.google.common.collect.Lists; -import java.math.BigDecimal; -import java.util.Collections; -import java.util.Comparator; -import java.util.EnumMap; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Stream; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; -import org.sonar.db.Pagination; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ProjectData; - -import static org.assertj.core.api.Assertions.assertThat; - -class ScaIssuesReleasesDetailsDaoIT { - - @RegisterExtension - private final DbTester db = DbTester.create(System2.INSTANCE); - - private final ScaIssuesReleasesDetailsDao scaIssuesReleasesDetailsDao = db.getDbClient().scaIssuesReleasesDetailsDao(); - - private static Comparator<ScaIssueReleaseDetailsDto> identityComparator() { - Function<ScaIssueReleaseDetailsDto, String> typeString = dto -> dto.scaIssueType().name(); - return Comparator.comparing(typeString) - .thenComparing(ScaIssueReleaseDetailsDto::vulnerabilityId) - .thenComparing(ScaIssueReleaseDetailsDto::issuePackageUrl) - .thenComparing(ScaIssueReleaseDetailsDto::spdxLicenseId) - .thenComparing(ScaIssueReleaseDetailsDto::issueReleaseUuid); - } - - private static Comparator<ScaIssueReleaseDetailsDto> severityComparator() { - return Comparator.comparing(dto -> dto.severity().databaseSortKey()); - } - - private static Comparator<ScaIssueReleaseDetailsDto> cvssScoreComparator() { - return Comparator.comparing(ScaIssueReleaseDetailsDto::cvssScore, - // we treat null cvss as a score of 0.0 - Comparator.nullsFirst(Comparator.naturalOrder())); - } - - private static Comparator<ScaIssueReleaseDetailsDto> comparator(ScaIssuesReleasesDetailsQuery.Sort sort) { - return switch (sort) { - case IDENTITY_ASC -> identityComparator(); - case IDENTITY_DESC -> identityComparator().reversed(); - case SEVERITY_ASC -> severityComparator() - .thenComparing(cvssScoreComparator()) - .thenComparing(identityComparator()); - case SEVERITY_DESC -> severityComparator().reversed() - .thenComparing(cvssScoreComparator().reversed()) - .thenComparing(identityComparator()); - case CVSS_SCORE_ASC -> cvssScoreComparator() - .thenComparing(ScaIssueReleaseDetailsDto::severity) - .thenComparing(identityComparator()); - case CVSS_SCORE_DESC -> cvssScoreComparator().reversed() - .thenComparing(Comparator.comparing(ScaIssueReleaseDetailsDto::severity).reversed()) - .thenComparing(identityComparator()); - }; - } - - @Test - void selectByBranchUuid_shouldReturnIssues() { - var projectData = db.components().insertPrivateProject(); - var componentDto = projectData.getMainBranchComponent(); - var issue1 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.VULNERABILITY, "1", componentDto.uuid()); - var issue2 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.PROHIBITED_LICENSE, "2", componentDto.uuid()); - - var foundPage = scaIssuesReleasesDetailsDao.selectByBranchUuid(db.getSession(), componentDto.branchUuid(), Pagination.forPage(1).andSize(1)); - - assertThat(foundPage).hasSize(1).isSubsetOf(issue1, issue2); - var foundAllIssues = scaIssuesReleasesDetailsDao.selectByBranchUuid(db.getSession(), componentDto.branchUuid(), Pagination.forPage(1).andSize(10)); - assertThat(foundAllIssues).hasSize(2).containsExactlyElementsOf(Stream.of(issue1, issue2).sorted(comparator(ScaIssuesReleasesDetailsQuery.Sort.SEVERITY_DESC)).toList()); - } - - @Test - void countByBranchUuid_shouldCountIssues() { - var componentDto = db.components().insertPrivateProject().getMainBranchComponent(); - db.getScaIssuesReleasesDetailsDbTester().insertVulnerabilityIssue("1", componentDto.uuid()); - db.getScaIssuesReleasesDetailsDbTester().insertVulnerabilityIssue("2", componentDto.uuid()); - db.getScaIssuesReleasesDetailsDbTester().insertVulnerabilityIssue("3", componentDto.uuid()); - - var count1 = scaIssuesReleasesDetailsDao.countByBranchUuid(db.getSession(), componentDto.branchUuid()); - assertThat(count1).isEqualTo(3); - - assertThat(scaIssuesReleasesDetailsDao.countByBranchUuid(db.getSession(), "bogus-branch-uuid")).isZero(); - } - - @Test - void selectByReleaseUuid_shouldReturnIssues() { - var projectData = db.components().insertPrivateProject(); - var componentDto = projectData.getMainBranchComponent(); - var issue1 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.VULNERABILITY, "1", componentDto.uuid()); - var release1 = issue1.releaseDto(); - // make these other issues use the same release and have a variety of CVSS - var issue2 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.VULNERABILITY, "2", componentDto.uuid(), - null, vi -> vi.toBuilder().setCvssScore(new BigDecimal("1.1")).build(), - releaseDto -> release1, - issueReleaseDto -> issueReleaseDto.toBuilder().setScaReleaseUuid(release1.uuid()).build()); - var issue3 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.VULNERABILITY, "3", componentDto.uuid(), - null, vi -> vi.toBuilder().setCvssScore(new BigDecimal("9.9")).build(), - releaseDto -> release1, - issueReleaseDto -> issueReleaseDto.toBuilder().setScaReleaseUuid(release1.uuid()).build()); - var issue4 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.PROHIBITED_LICENSE, "4", componentDto.uuid(), - null, null, - releaseDto -> release1, - issueReleaseDto -> issueReleaseDto.toBuilder().setScaReleaseUuid(release1.uuid()).build()); - - var foundPage = scaIssuesReleasesDetailsDao.selectByBranchUuid(db.getSession(), componentDto.branchUuid(), Pagination.forPage(1).andSize(1)); - - assertThat(foundPage).hasSize(1).isSubsetOf(issue1, issue2, issue3, issue4); - var foundAllIssues = scaIssuesReleasesDetailsDao.selectByBranchUuid(db.getSession(), componentDto.branchUuid(), Pagination.forPage(1).andSize(10)); - assertThat(foundAllIssues).hasSize(4) - .containsExactlyElementsOf(Stream.of(issue1, issue2, issue3, issue4).sorted(comparator(ScaIssuesReleasesDetailsQuery.Sort.SEVERITY_DESC)).toList()); - } - - @Test - void withNoQueryFilters_shouldReturnAllIssues() { - setupAndExecuteQueryTest(Function.identity(), QueryTestData::expectedIssuesSortedByIdentityAsc, "All issues should be returned"); - } - - @Test - void withNoQueryFilters_shouldCountAllIssues() { - setupAndExecuteQueryCountTest(Function.identity(), 6); - } - - @Test - void withNoQueryFilters_shouldSort() { - QueryTestData testData = createQueryTestData(); - var expectedLists = new EnumMap<ScaIssuesReleasesDetailsQuery.Sort, List<ScaIssueReleaseDetailsDto>>(ScaIssuesReleasesDetailsQuery.Sort.class); - for (var sort : ScaIssuesReleasesDetailsQuery.Sort.values()) { - var expectedIssues = testData.expectedIssuesSorted(sort); - executeQueryTest(testData, queryBuilder -> queryBuilder.setSort(sort), expectedIssues, - "Sort %s should return expected issues".formatted(sort)); - expectedLists.put(sort, expectedIssues); - } - - // The assertions below here are actually about the expectations, but above - // we've just established that the actual matches the expectations. - - // The point of this is to assert that the test data contains a distinct ordering for each - // ordering in ScaIssuesReleasesDetailsQuery.Sort, because if it doesn't we could get - // false negatives in our tests. - assertThat(expectedLists.values().stream().distinct().toList()) - .as("Expected issues should have distinct orderings for each sort") - .containsExactlyInAnyOrderElementsOf(expectedLists.values()); - - // for identity, assert that our ASC and DESC actually invert each other. - // for severity and cvss score, this isn't supposed to be true because the - // secondary sort is IDENTITY_ASC even when we sort by DESC severity; but the - // severity and score values ignoring the other attributes should still be - // reversed. - assertThat(Lists.reverse(expectedLists.get(ScaIssuesReleasesDetailsQuery.Sort.IDENTITY_ASC))) - .as("IDENTITY sort should be reversed when sorted by DESC") - .containsExactlyElementsOf(expectedLists.get(ScaIssuesReleasesDetailsQuery.Sort.IDENTITY_DESC)); - assertThat( - Lists.reverse(expectedLists.get(ScaIssuesReleasesDetailsQuery.Sort.SEVERITY_ASC)).stream() - .map(ScaIssueReleaseDetailsDto::severity) - .toList()) - .as("SEVERITY sort should be reversed when sorted by DESC") - .containsExactlyElementsOf(expectedLists.get(ScaIssuesReleasesDetailsQuery.Sort.SEVERITY_DESC).stream() - .map(ScaIssueReleaseDetailsDto::severity) - .toList()); - assertThat(Lists.reverse(expectedLists.get(ScaIssuesReleasesDetailsQuery.Sort.CVSS_SCORE_ASC).stream() - .map(ScaIssueReleaseDetailsDto::cvssScore) - .toList())) - .as("CVSS_SCORE sort should be reversed when sorted by DESC") - .containsExactlyElementsOf(expectedLists.get(ScaIssuesReleasesDetailsQuery.Sort.CVSS_SCORE_DESC).stream() - .map(ScaIssueReleaseDetailsDto::cvssScore) - .toList()); - } - - @Test - void withQueryFilteredByIssueType_shouldReturnExpectedTypes() { - QueryTestData testData = createQueryTestData(); - executeQueryTest(testData, - queryBuilder -> queryBuilder.setTypes(List.of(ScaIssueType.VULNERABILITY)), - testData.expectedIssuesSortedByIdentityAsc().stream() - .filter(expected -> expected.scaIssueType() == ScaIssueType.VULNERABILITY) - .toList(), - "Only vulnerability issues should be returned"); - executeQueryTest(testData, - queryBuilder -> queryBuilder.setTypes(List.of(ScaIssueType.PROHIBITED_LICENSE)), - testData.expectedIssuesSortedByIdentityAsc().stream() - .filter(expected -> expected.scaIssueType() == ScaIssueType.PROHIBITED_LICENSE) - .toList(), - "Only vulnerability issues should be returned"); - executeQueryTest(testData, - queryBuilder -> queryBuilder.setTypes(List.of(ScaIssueType.values())), - testData.expectedIssuesSortedByIdentityAsc(), - "All issues should be returned"); - executeQueryTest(testData, - queryBuilder -> queryBuilder.setTypes(Collections.emptyList()), - Collections.emptyList(), - "No issues should be returned when searching for zero types"); - } - - @Test - void withQueryFilteredByIssueType_shouldCountSelectedIssues() { - QueryTestData testData = createQueryTestData(); - executeQueryCountTest(testData, - queryBuilder -> queryBuilder.setTypes(List.of(ScaIssueType.VULNERABILITY)), - 4); - executeQueryCountTest(testData, - queryBuilder -> queryBuilder.setTypes(List.of(ScaIssueType.PROHIBITED_LICENSE)), - 2); - executeQueryCountTest(testData, - queryBuilder -> queryBuilder.setTypes(List.of(ScaIssueType.values())), - 6); - executeQueryCountTest(testData, - queryBuilder -> queryBuilder.setTypes(Collections.emptyList()), - 0); - } - - @Test - void withQueryFilteredByVulnerabilityId_shouldReturnExpectedItems() { - QueryTestData testData = createQueryTestData(); - var expectedEndsInId1 = testData.expectedIssues().stream() - .filter(issue -> issue.vulnerabilityId() != null && issue.vulnerabilityId().endsWith("Id1")) - .toList(); - assertThat(expectedEndsInId1).hasSize(1); - executeQueryTest(testData, - queryBuilder -> queryBuilder.setVulnerabilityIdSubstring("Id1"), - expectedEndsInId1, - "Only the vulnerability ending in Id1 should be returned"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setVulnerabilityIdSubstring("NotInThere"), - Collections.emptyList(), - "No issues should be returned when searching for the substring 'NotInThere'"); - executeQueryTest(testData, - queryBuilder -> queryBuilder.setVulnerabilityIdSubstring("Escape% NULL AS!%"), - Collections.emptyList(), - "No issues should be returned when searching for a string that needs escaping"); - executeQueryTest(testData, - queryBuilder -> queryBuilder.setVulnerabilityIdSubstring(ScaIssueDto.NULL_VALUE), - Collections.emptyList(), - "No vulnerabilities should be returned when searching for ScaIssueDto.NULL_VALUE"); - - var allVulnerabilityIssues = testData.expectedIssuesSortedByIdentityAsc().stream() - .filter(issue -> issue.scaIssueType() == ScaIssueType.VULNERABILITY) - .toList(); - assertThat(allVulnerabilityIssues).hasSize(4); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setVulnerabilityIdSubstring("Vulnerability"), - allVulnerabilityIssues, - "All vulnerabilities should be returned when searching for the substring 'Vulnerability'"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setVulnerabilityIdSubstring(""), - allVulnerabilityIssues, - "All vulnerabilities should be returned when searching for empty vulnerabilityId"); - } - - @Test - void withQueryFilteredByPackageName_shouldReturnExpectedItems() { - QueryTestData testData = createQueryTestData(); - var expectedEndsInName1 = testData.expectedIssues().subList(0, 1); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setPackageNameSubstring("Name1"), - expectedEndsInName1, - "Only the packages containing Name1 should be returned"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setPackageNameSubstring("NotInThere"), - Collections.emptyList(), - "No issues should be returned when searching for the substring 'NotInThere'"); - executeQueryTest(testData, - queryBuilder -> queryBuilder.setPackageNameSubstring("Escape% NULL AS!%"), - Collections.emptyList(), - "No issues should be returned when searching for a string that needs escaping"); - executeQueryTest(testData, - queryBuilder -> queryBuilder.setPackageNameSubstring(ScaIssueDto.NULL_VALUE), - Collections.emptyList(), - "No vulnerabilities should be returned when searching for ScaIssueDto.NULL_VALUE"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setPackageNameSubstring("Package"), - testData.expectedIssuesSortedByIdentityAsc(), - "All issues should be returned when searching for the substring 'Package'"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setPackageNameSubstring(""), - testData.expectedIssuesSortedByIdentityAsc(), - "All issues should be returned when searching for empty package name"); - } - - @Test - void withQueryFilteredByNewInPullRequest_shouldReturnExpectedItems() { - QueryTestData testData = createQueryTestData(); - - var expectedNew = testData.expectedIssuesSortedByIdentityAsc().stream() - .filter(issue -> issue.newInPullRequest()) - .toList(); - var expectedNotNew = testData.expectedIssuesSortedByIdentityAsc().stream() - .filter(issue -> !issue.newInPullRequest()) - .toList(); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setNewInPullRequest(true), - expectedNew, - "Only the releases marked newInPullRequest should be returned"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setNewInPullRequest(false), - expectedNotNew, - "Only the releases marked not newInPullRequest should be returned"); - } - - @Test - void withQueryFilteredBySeverity_shouldReturnExpectedItems() { - QueryTestData testData = createQueryTestData(); - var expectedSeverityInfo = testData.expectedIssuesSortedByIdentityAsc().stream() - .filter(issue -> issue.severity() == ScaSeverity.INFO) - .toList(); - var expectedSeverityBlocker = testData.expectedIssuesSortedByIdentityAsc().stream() - .filter(issue -> issue.severity() == ScaSeverity.BLOCKER) - .toList(); - assertThat(expectedSeverityInfo).hasSize(5); - assertThat(expectedSeverityBlocker).hasSize(1); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setSeverities(List.of(ScaSeverity.INFO)), - expectedSeverityInfo, - "Only the issues of severity INFO should be returned"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setSeverities(List.of(ScaSeverity.BLOCKER)), - expectedSeverityBlocker, - "Only the issues of severity BLOCKER should be returned"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setSeverities(List.of(ScaSeverity.LOW, ScaSeverity.HIGH)), - Collections.emptyList(), - "Should not match any severities of LOW or HIGH"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setSeverities(List.of(ScaSeverity.BLOCKER, ScaSeverity.INFO, ScaSeverity.LOW)), - testData.expectedIssuesSortedByIdentityAsc(), - "All issues should be returned when searching for a list that contains them all"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setSeverities(Collections.emptyList()), - Collections.emptyList(), - "No issues should be returned when searching for zero severities"); - } - - @Test - void withQueryFilteredByPackageManager_shouldReturnExpectedItems() { - QueryTestData testData = createQueryTestData(); - var expectedPackageManagerNpm = testData.expectedIssuesWithPackageManager(PackageManager.NPM).stream() - .sorted(identityComparator()).toList(); - var expectedPackageManagerMaven = testData.expectedIssuesWithPackageManager(PackageManager.MAVEN).stream() - .sorted(identityComparator()).toList(); - - assertThat(expectedPackageManagerNpm).hasSize(2); - assertThat(expectedPackageManagerMaven).hasSize(4); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setPackageManagers(List.of(PackageManager.NPM)), - expectedPackageManagerNpm, - "Only the npm issues should be returned"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setPackageManagers(List.of(PackageManager.MAVEN)), - expectedPackageManagerMaven, - "Only the Maven issues should be returned"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setPackageManagers(List.of(PackageManager.NPM, PackageManager.MAVEN)), - testData.expectedIssuesSortedByIdentityAsc(), - "All issues should be returned when searching for two package managers"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setPackageManagers(Collections.emptyList()), - Collections.emptyList(), - "No issues should be returned when searching for zero package managers"); - } - - @Test - void withQueryFilteredByDirect_shouldReturnExpectedItems() { - QueryTestData testData = createQueryTestData(); - var expectedDirect = testData.directIssues(); - var expectedTransitive = testData.transitiveIssues(); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setDirect(true), - expectedDirect, - "Only direct issues should be returned"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setDirect(false), - expectedTransitive, - "Only the transitive issues should be returned"); - } - - @Test - void withQueryFilteredByProductionScope_shouldReturnExpectedItems() { - QueryTestData testData = createQueryTestData(); - var expectedProduction = testData.productionIssues(); - var expectedNotProduction = testData.notProductionIssues(); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setProductionScope(true), - expectedProduction, - "Only production issues should be returned"); - - executeQueryTest(testData, - queryBuilder -> queryBuilder.setProductionScope(false), - expectedNotProduction, - "Only the non-production issues should be returned"); - } - - @Test - void withQueryMultipleFiltersNonDefaultSort_shouldReturnExpectedItems() { - QueryTestData testData = createQueryTestData(); - var expectedPackageManagerMaven = testData.expectedIssuesWithPackageManager(PackageManager.MAVEN); - var expectedTypeVulnerability = testData.expectedIssuesSortedByIdentityAsc().stream() - .filter(issue -> issue.scaIssueType() == ScaIssueType.VULNERABILITY) - .toList(); - var sortedByCvssDesc = testData.expectedIssuesSortedByCvssDesc(); - var expectedResults = sortedByCvssDesc.stream() - .filter(expectedPackageManagerMaven::contains) - .filter(expectedTypeVulnerability::contains) - .toList(); - assertThat(expectedResults).hasSize(3); - - executeQueryTest(testData, - queryBuilder -> queryBuilder - .setSort(ScaIssuesReleasesDetailsQuery.Sort.CVSS_SCORE_DESC) - .setPackageManagers(List.of(PackageManager.MAVEN)) - .setTypes(List.of(ScaIssueType.VULNERABILITY)), - expectedResults, - "Maven vulnerabilities returned in cvss score desc order"); - } - - private void setupAndExecuteQueryTest(Function<ScaIssuesReleasesDetailsQuery.Builder, ScaIssuesReleasesDetailsQuery.Builder> builderFunction, - Function<QueryTestData, List<ScaIssueReleaseDetailsDto>> expectedIssuesFunction, String assertAs) { - QueryTestData testData = createQueryTestData(); - executeQueryTest(testData, builderFunction, expectedIssuesFunction.apply(testData), assertAs); - } - - private void executeQueryTest(QueryTestData testData, - Function<ScaIssuesReleasesDetailsQuery.Builder, ScaIssuesReleasesDetailsQuery.Builder> builderFunction, - List<ScaIssueReleaseDetailsDto> expectedIssues, - String assertAs) { - var query = builderFunction.apply( - new ScaIssuesReleasesDetailsQuery.Builder() - .setBranchUuid(testData.branchUuid()) - .setSort(ScaIssuesReleasesDetailsQuery.Sort.IDENTITY_ASC)) - .build(); - var foundPage = scaIssuesReleasesDetailsDao.selectByQuery(db.getSession(), query, Pagination.forPage(1).andSize(10)); - - assertThat(foundPage).as(assertAs).containsExactlyElementsOf(expectedIssues); - } - - private void setupAndExecuteQueryCountTest(Function<ScaIssuesReleasesDetailsQuery.Builder, ScaIssuesReleasesDetailsQuery.Builder> builderFunction, - int expectedCount) { - QueryTestData testData = createQueryTestData(); - executeQueryCountTest(testData, builderFunction, expectedCount); - } - - private void executeQueryCountTest(QueryTestData testData, - Function<ScaIssuesReleasesDetailsQuery.Builder, ScaIssuesReleasesDetailsQuery.Builder> builderFunction, - int expectedCount) { - var query = builderFunction.apply( - new ScaIssuesReleasesDetailsQuery.Builder() - .setBranchUuid(testData.branchUuid()) - .setSort(ScaIssuesReleasesDetailsQuery.Sort.IDENTITY_ASC)) - .build(); - var count = scaIssuesReleasesDetailsDao.countByQuery(db.getSession(), query); - - assertThat(count).isEqualTo(expectedCount); - } - - private QueryTestData createQueryTestData() { - var projectData = db.components().insertPrivateProject(); - var componentDto = projectData.getMainBranchComponent(); - // the first two are set to NPM, the others default to MAVEN - var issue1 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.VULNERABILITY, "1", componentDto.uuid(), - scaIssueDto -> scaIssueDto, - scaVulnerabilityIssueDto -> scaVulnerabilityIssueDto, - scaReleaseDto -> scaReleaseDto.toBuilder().setPackageManager(PackageManager.NPM).build(), - scaIssueReleaseDto -> scaIssueReleaseDto); - var issue2 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.PROHIBITED_LICENSE, "2", componentDto.uuid(), - scaIssueDto -> scaIssueDto, - scaVulnerabilityIssueDto -> scaVulnerabilityIssueDto, - scaReleaseDto -> scaReleaseDto.toBuilder().setPackageManager(PackageManager.NPM).build(), - scaIssueReleaseDto -> scaIssueReleaseDto); - var issue3 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.VULNERABILITY, "3", componentDto.uuid()); - var issue4 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.PROHIBITED_LICENSE, "4", componentDto.uuid()); - // low cvss but high severity - var issue5 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.VULNERABILITY, "5", componentDto.uuid(), - scaIssueDto -> scaIssueDto, - scaVulnerabilityIssueDto -> scaVulnerabilityIssueDto.toBuilder() - .setCvssScore(new BigDecimal("2.1")) - .setBaseSeverity(ScaSeverity.BLOCKER) - .build(), - scaReleaseDto -> scaReleaseDto.toBuilder().setNewInPullRequest(true).build(), - scaIssueReleaseDto -> scaIssueReleaseDto.toBuilder().setSeverity(ScaSeverity.BLOCKER).build()); - // high cvss but low severity - var issue6 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.VULNERABILITY, "6", componentDto.uuid(), - scaIssueDto -> scaIssueDto, - scaVulnerabilityIssueDto -> scaVulnerabilityIssueDto.toBuilder() - .setCvssScore(new BigDecimal("9.1")) - .setBaseSeverity(ScaSeverity.INFO) - .build(), - scaReleaseDto -> scaReleaseDto.toBuilder().setNewInPullRequest(true).build(), - scaIssueReleaseDto -> scaIssueReleaseDto.toBuilder().setSeverity(ScaSeverity.INFO).build()); - - // issue 1 weirdly has no dependency, issues 2-3 are direct, issues 4-6 are transitive - // issues 2 and 4 are production, 3,5,6 are not production - db.getScaDependenciesDbTester().insertScaDependency(issue2.releaseUuid(), "2", - builder -> builder.setDirect(true).setProductionScope(true)); - var dep3 = db.getScaDependenciesDbTester().insertScaDependency(issue3.releaseUuid(), "3", - builder -> builder.setDirect(true).setProductionScope(false)); - var dep4 = db.getScaDependenciesDbTester().insertScaDependency(issue4.releaseUuid(), "4", - builder -> builder.setDirect(false).setProductionScope(true)); - var dep5 = db.getScaDependenciesDbTester().insertScaDependency(issue5.releaseUuid(), "5", - builder -> builder.setDirect(false).setProductionScope(false)); - db.getScaDependenciesDbTester().insertScaDependency(issue6.releaseUuid(), "6", - builder -> builder.setDirect(false).setProductionScope(false)); - - // make issue3 and issue4 BOTH direct and transitive, - // issue4 and issue5 are BOTH production and not - db.getScaDependenciesDbTester().insertScaDependency(issue3.releaseUuid(), "7", - builder -> builder.setDirect(!dep3.direct()).setProductionScope(dep3.productionScope())); - db.getScaDependenciesDbTester().insertScaDependency(issue4.releaseUuid(), "8", - builder -> builder.setDirect(!dep4.direct()).setProductionScope(!dep4.productionScope())); - db.getScaDependenciesDbTester().insertScaDependency(issue5.releaseUuid(), "9", - builder -> builder.setDirect(dep5.direct()).setProductionScope(!dep5.productionScope())); - - var directIssues = List.of(issue2, issue3, issue4).stream().sorted(identityComparator()).toList(); - var transitiveIssues = List.of(issue3, issue4, issue5, issue6).stream().sorted(identityComparator()).toList(); - var productionIssues = List.of(issue2, issue4, issue5).stream().sorted(identityComparator()).toList(); - var notProductionIssues = List.of(issue3, issue4, issue5, issue6).stream().sorted(identityComparator()).toList(); - - return new QueryTestData(projectData, componentDto, - List.of(issue1, issue2, issue3, issue4, issue5, issue6), - directIssues, transitiveIssues, productionIssues, notProductionIssues); - } - - @Test - void selectByScaIssueReleaseUuid_shouldReturnAnIssue() { - var projectData = db.components().insertPrivateProject(); - var componentDto = projectData.getMainBranchComponent(); - var issue1 = db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.VULNERABILITY, "1", componentDto.uuid()); - - // insert another issue to assert that it's not selected - db.getScaIssuesReleasesDetailsDbTester().insertIssue(ScaIssueType.PROHIBITED_LICENSE, "2", componentDto.uuid()); - - var foundIssue = scaIssuesReleasesDetailsDao.selectByScaIssueReleaseUuid(db.getSession(), issue1.issueReleaseUuid()); - assertThat(foundIssue).isEqualTo(issue1); - - var notFoundIssue = scaIssuesReleasesDetailsDao.selectByScaIssueReleaseUuid(db.getSession(), "00000"); - assertThat(notFoundIssue).isNull(); - } - - private record QueryTestData(ProjectData projectData, - ComponentDto componentDto, - List<ScaIssueReleaseDetailsDto> expectedIssues, - List<ScaIssueReleaseDetailsDto> directIssues, - List<ScaIssueReleaseDetailsDto> transitiveIssues, - List<ScaIssueReleaseDetailsDto> productionIssues, - List<ScaIssueReleaseDetailsDto> notProductionIssues) { - - public String branchUuid() { - return componentDto.branchUuid(); - } - - public List<ScaIssueReleaseDetailsDto> expectedIssuesSorted(ScaIssuesReleasesDetailsQuery.Sort sort) { - return expectedIssues.stream().sorted(comparator(sort)).toList(); - } - - public List<ScaIssueReleaseDetailsDto> expectedIssuesSortedByIdentityAsc() { - return expectedIssuesSorted(ScaIssuesReleasesDetailsQuery.Sort.IDENTITY_ASC); - } - - public List<ScaIssueReleaseDetailsDto> expectedIssuesSortedByCvssDesc() { - return expectedIssuesSorted(ScaIssuesReleasesDetailsQuery.Sort.CVSS_SCORE_DESC); - } - - public List<ScaIssueReleaseDetailsDto> expectedIssuesWithPackageManager(PackageManager packageManager) { - // we just have hardcoded knowledge of how we set them up, because ScaIssueReleaseDetailsDto doesn't - // contain the ScaReleaseDto to look at this - return switch (packageManager) { - case NPM -> expectedIssues.subList(0, 2); - case MAVEN -> expectedIssues.subList(2, expectedIssues.size()); - default -> Collections.emptyList(); - }; - } - } -} diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaReleasesDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaReleasesDaoIT.java deleted file mode 100644 index f59f2fbf39c..00000000000 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaReleasesDaoIT.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; -import org.assertj.core.groups.Tuple; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.slf4j.LoggerFactory; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; -import org.sonar.db.Pagination; -import org.sonar.db.component.ComponentDto; -import org.sonar.db.component.ProjectData; - -import static org.assertj.core.api.Assertions.assertThat; - -class ScaReleasesDaoIT { - - @RegisterExtension - private final DbTester db = DbTester.create(System2.INSTANCE); - - private final ScaReleasesDao scaReleasesDao = db.getDbClient().scaReleasesDao(); - - @Test - void insert_shouldPersistScaReleases() { - ComponentDto componentDto = prepareComponentDto(); - ScaReleaseDto scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1"); - - List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_releases"); - assertThat(select).hasSize(1); - Map<String, Object> stringObjectMap = select.get(0); - assertThat(stringObjectMap).containsExactlyInAnyOrderEntriesOf( - Map.ofEntries( - Map.entry("uuid", scaReleaseDto.uuid()), - Map.entry("component_uuid", scaReleaseDto.componentUuid()), - Map.entry("package_url", scaReleaseDto.packageUrl()), - Map.entry("package_manager", scaReleaseDto.packageManager().name()), - Map.entry("package_name", scaReleaseDto.packageName()), - Map.entry("version", scaReleaseDto.version()), - Map.entry("license_expression", scaReleaseDto.licenseExpression()), - Map.entry("declared_license_expression", scaReleaseDto.declaredLicenseExpression()), - Map.entry("known", scaReleaseDto.known()), - Map.entry("new_in_pull_request", scaReleaseDto.newInPullRequest()), - Map.entry("created_at", scaReleaseDto.createdAt()), - Map.entry("updated_at", scaReleaseDto.updatedAt()))); - } - - @Test - void deleteByUuid_shouldDeleteScaReleases() { - ComponentDto componentDto = prepareComponentDto(); - ScaReleaseDto scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1"); - - List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_releases"); - assertThat(select).isNotEmpty(); - - scaReleasesDao.deleteByUuid(db.getSession(), scaReleaseDto.uuid()); - - select = db.select(db.getSession(), "select * from sca_releases"); - assertThat(select).isEmpty(); - } - - @Test - void selectByUuid_shouldLoadScaRelease() { - ComponentDto componentDto = prepareComponentDto(); - ScaReleaseDto scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1"); - - var loadedOptional = scaReleasesDao.selectByUuid(db.getSession(), scaReleaseDto.uuid()); - - assertThat(loadedOptional).contains(scaReleaseDto); - } - - @Test - void selectByUuid_shouldLoadScaReleases() { - ComponentDto componentDto = prepareComponentDto(); - ScaReleaseDto scaReleaseDto1 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1"); - db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "2"); - ScaReleaseDto scaReleaseDto3 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "3"); - - // we don't ask for the second one, so this tests we only get what we asked for. - var loaded = scaReleasesDao.selectByUuids(db.getSession(), Set.of(scaReleaseDto1.uuid(), scaReleaseDto3.uuid())); - - assertThat(loaded).containsExactlyInAnyOrder(scaReleaseDto1, scaReleaseDto3); - } - - @Test - void selectByUuid_shouldLoadEmptyScaReleases() { - ComponentDto componentDto = prepareComponentDto(); - db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1"); - db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "2"); - db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "3"); - - var loaded = scaReleasesDao.selectByUuids(db.getSession(), Collections.emptyList()); - - assertThat(loaded).isEmpty(); - } - - @Test - void selectByQuery_shouldReturnScaReleases_whenQueryByBranchUuid() { - ComponentDto componentDto = prepareComponentDto(); - ScaReleaseDto scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1"); - System.out.println("componentDto = " + componentDto); - - ScaReleasesQuery scaReleasesQuery = new ScaReleasesQuery(componentDto.branchUuid(), null, null, null, null, null); - List<ScaReleaseDto> results = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesQuery, Pagination.all()); - - assertThat(results).hasSize(1); - assertThat(results.get(0)).usingRecursiveComparison().isEqualTo(scaReleaseDto); - } - - @Test - void selectByQuery_shouldReturnPaginatedScaReleases() { - ComponentDto componentDto = prepareComponentDto(); - ScaReleaseDto scaReleaseDto1 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1"); - ScaReleaseDto scaReleaseDto2 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "2"); - ScaReleaseDto scaReleaseDto3 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "3"); - ScaReleaseDto scaReleaseDto4 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "4"); - - ScaReleasesQuery scaReleasesQuery = new ScaReleasesQuery(componentDto.branchUuid(), null, null, null, null, null); - List<ScaReleaseDto> page1Results = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesQuery, Pagination.forPage(1).andSize(2)); - List<ScaReleaseDto> page2Results = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesQuery, Pagination.forPage(2).andSize(2)); - - // we order by created_at so it would seem we can assert the order here... except that created_at has finite resolution, so it can be nondeterministic. - var allResults = new ArrayList<>(page1Results); - allResults.addAll(page2Results); - assertThat(allResults).containsExactlyInAnyOrder(scaReleaseDto1, scaReleaseDto2, scaReleaseDto3, scaReleaseDto4); - assertThat(List.of(page1Results.size(), page2Results.size())).containsExactly(2, 2); - } - - @Test - void selectByQuery_shouldPartiallyMatchPackageName_whenQueriedByText() { - ComponentDto componentDto = prepareComponentDto(); - ScaReleaseDto scaReleaseDto1 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1", PackageManager.MAVEN, "foo.bar"); - db.getScaDependenciesDbTester().insertScaDependency(scaReleaseDto1, "1", true); - db.getScaDependenciesDbTester().insertScaDependency(scaReleaseDto1, "2", false); - var log = LoggerFactory.getLogger(""); - List<Map<String, Object>> temp = db.select(db.getSession(), "select * from sca_releases"); - log.warn("sca_releases: {}", temp.stream().count()); - for (Map<String, Object> map : temp) { - log.warn(map.toString()); - } - temp = db.select(db.getSession(), "select * from sca_dependencies"); - log.warn("sca_dependencies: {}", temp.stream().count()); - for (Map<String, Object> map : temp) { - log.warn(map.toString()); - } - - @SuppressWarnings("unused") - ScaReleaseDto scaReleaseDto2 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "2", PackageManager.MAVEN, "bar.mee"); - ScaReleaseDto scaReleaseDto3 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "3", PackageManager.MAVEN, "foo.bar.me"); - @SuppressWarnings("unused") - ScaReleaseDto scaReleaseDto4 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "4", PackageManager.MAVEN, "some.foo.bar"); - - ScaReleasesQuery scaReleasesQuery = new ScaReleasesQuery(componentDto.branchUuid(), null, null, null, null, "foo"); - List<ScaReleaseDto> results = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesQuery, Pagination.all()); - - assertThat(results).hasSize(3); - assertThat(results.get(0)).usingRecursiveComparison().isEqualTo(scaReleaseDto1); - assertThat(results.get(1)).usingRecursiveComparison().isEqualTo(scaReleaseDto3); - - ScaReleasesQuery scaReleasesCaseInsensitiveQuery = new ScaReleasesQuery(componentDto.branchUuid(), null, null, null, null, "Foo.Bar"); - List<ScaReleaseDto> resultsCaseInsensitive = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesCaseInsensitiveQuery, Pagination.all()); - - assertThat(resultsCaseInsensitive).hasSize(3); - assertThat(resultsCaseInsensitive.get(0)).usingRecursiveComparison().isEqualTo(scaReleaseDto1); - assertThat(resultsCaseInsensitive.get(1)).usingRecursiveComparison().isEqualTo(scaReleaseDto3); - } - - @Test - void selectByQuery_shouldReturnScaReleases_whenQueryByDirect() { - ComponentDto componentDto = prepareComponentDto(); - ScaReleaseDto scaReleaseDto1 = db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto.uuid(), "1", 2, true, PackageManager.MAVEN, "foo.bar"); - ScaReleaseDto scaReleaseDto2 = db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto.uuid(), "2", 3, false, PackageManager.MAVEN, "foo.bar"); - - ScaReleasesQuery scaReleasesDirectQuery = new ScaReleasesQuery(componentDto.branchUuid(), true, null, null, null, null); - List<ScaReleaseDto> resultsDirect = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesDirectQuery, Pagination.all()); - - assertThat(resultsDirect).hasSize(1); - assertThat(resultsDirect.get(0)).usingRecursiveComparison().isEqualTo(scaReleaseDto1); - - ScaReleasesQuery scaReleasesNoDirectQuery = new ScaReleasesQuery(componentDto.branchUuid(), false, null, null, null, null); - List<ScaReleaseDto> resultsNoDirect = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesNoDirectQuery, Pagination.all()); - - assertThat(resultsNoDirect).hasSize(1); - assertThat(resultsNoDirect.get(0)).usingRecursiveComparison().isEqualTo(scaReleaseDto2); - } - - @Test - void selectByQuery_shouldReturnScaReleases_whenQueryByProductionScope() { - ComponentDto componentDto = prepareComponentDto(); - ScaReleaseDto scaReleaseDto1 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1"); - ScaReleaseDto scaReleaseDto2 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "2"); - db.getScaDependenciesDbTester().insertScaDependency(scaReleaseDto1, "1", builder -> builder.setProductionScope(true)); - db.getScaDependenciesDbTester().insertScaDependency(scaReleaseDto2, "2", builder -> builder.setProductionScope(false)); - - ScaReleasesQuery scaReleasesProductionScopeQuery = new ScaReleasesQuery(componentDto.branchUuid(), null, true, null, null, null); - List<ScaReleaseDto> resultsProductionScope = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesProductionScopeQuery, Pagination.all()); - - assertThat(resultsProductionScope).hasSize(1); - assertThat(resultsProductionScope.get(0)).usingRecursiveComparison().isEqualTo(scaReleaseDto1); - - ScaReleasesQuery scaReleasesNoProductionScopeQuery = new ScaReleasesQuery(componentDto.branchUuid(), null, false, null, null, null); - List<ScaReleaseDto> resultsNoProductionScope = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesNoProductionScopeQuery, Pagination.all()); - - assertThat(resultsNoProductionScope).hasSize(1); - assertThat(resultsNoProductionScope.get(0)).usingRecursiveComparison().isEqualTo(scaReleaseDto2); - } - - @Test - void selectByQuery_shouldReturnScaReleases_whenQueryByPackageManager() { - ComponentDto componentDto = prepareComponentDto(); - ScaReleaseDto scaReleaseDto1 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1", PackageManager.MAVEN, "foo.bar"); - ScaReleaseDto scaReleaseDto2 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "2", PackageManager.NPM, "foo.bar"); - ScaReleaseDto scaReleaseDto3 = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "3", PackageManager.CARGO, "foo.bar"); - - ScaReleasesQuery scaReleasesMavenQuery = new ScaReleasesQuery(componentDto.branchUuid(), null, null, List.of(PackageManager.MAVEN.name()), null, null); - List<ScaReleaseDto> resultsMaven = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesMavenQuery, Pagination.all()); - - assertThat(resultsMaven).hasSize(1); - assertThat(resultsMaven.get(0)).usingRecursiveComparison().isEqualTo(scaReleaseDto1); - - ScaReleasesQuery scaReleasesNpmAndCargoQuery = new ScaReleasesQuery(componentDto.branchUuid(), null, null, - List.of(PackageManager.NPM.name(), PackageManager.CARGO.name()), null, null); - List<ScaReleaseDto> resultsNpm = scaReleasesDao.selectByQuery(db.getSession(), scaReleasesNpmAndCargoQuery, Pagination.all()); - - assertThat(resultsNpm).hasSize(2); - assertThat(resultsNpm.get(0)).usingRecursiveComparison().isEqualTo(scaReleaseDto2); - assertThat(resultsNpm.get(1)).usingRecursiveComparison().isEqualTo(scaReleaseDto3); - } - - @Test - void update_shouldUpdateScaRelease() { - ComponentDto componentDto = prepareComponentDto(); - ScaReleaseDto scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentDto.uuid(), "1", PackageManager.MAVEN, "foo.bar"); - ScaReleaseDto updatedScaRelease = scaReleaseDto.toBuilder().setUpdatedAt(scaReleaseDto.updatedAt() + 1).setVersion("newVersion").build(); - - scaReleasesDao.update(db.getSession(), updatedScaRelease); - - List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_releases"); - assertThat(select).hasSize(1); - Map<String, Object> stringObjectMap = select.get(0); - assertThat(stringObjectMap).containsExactlyInAnyOrderEntriesOf( - Map.ofEntries( - Map.entry("uuid", updatedScaRelease.uuid()), - Map.entry("component_uuid", updatedScaRelease.componentUuid()), - Map.entry("package_url", updatedScaRelease.packageUrl()), - Map.entry("package_manager", updatedScaRelease.packageManager().name()), - Map.entry("package_name", updatedScaRelease.packageName()), - Map.entry("version", updatedScaRelease.version()), - Map.entry("license_expression", updatedScaRelease.licenseExpression()), - Map.entry("declared_license_expression", updatedScaRelease.declaredLicenseExpression()), - Map.entry("known", updatedScaRelease.known()), - Map.entry("new_in_pull_request", updatedScaRelease.newInPullRequest()), - Map.entry("created_at", updatedScaRelease.createdAt()), - Map.entry("updated_at", updatedScaRelease.updatedAt()))); - } - - @Test - void countByQuery_shouldReturnTheTotalOfReleases() { - ComponentDto componentDto1 = prepareComponentDto(); - db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "1", 1, true, PackageManager.MAVEN, "foo.bar"); - db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "2", 2, true, PackageManager.MAVEN, "foo.bar.mee"); - db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "3", 3, true, PackageManager.MAVEN, "bar.fo"); - - ScaReleasesQuery scaReleasesQuery = new ScaReleasesQuery(componentDto1.branchUuid(), null, null, null, null, "foo"); - - assertThat(scaReleasesDao.countByQuery(db.getSession(), scaReleasesQuery)).isEqualTo(2); - assertThat(scaReleasesDao.countByQuery(db.getSession(), new ScaReleasesQuery(componentDto1.branchUuid(), null, null, null, null, null))).isEqualTo(3); - assertThat(scaReleasesDao.countByQuery(db.getSession(), new ScaReleasesQuery("another_branch_uuid", null, null, null, null, null))).isZero(); - } - - private ComponentDto prepareComponentDto() { - ProjectData projectData = db.components().insertPublicProject(); - return projectData.getMainBranchComponent(); - } - - @Test - void countByPlatformQuery_shouldReturnPlatforms() { - ComponentDto componentDto1 = prepareComponentDto(); - db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "1", 1, true, PackageManager.MAVEN, "foo.bar"); - db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "2", 2, true, PackageManager.NPM, "foo.bar.mee"); - db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "3", 3, true, PackageManager.MAVEN, "bar.foo"); - db.getScaReleasesDbTester().insertScaReleaseWithDependency(componentDto1.uuid(), "4", 4, true, PackageManager.PYPI, "bar.foo"); - - ScaReleasesQuery scaReleasesQuery = new ScaReleasesQuery(componentDto1.branchUuid(), null, null, null, null, null); - - List<ScaReleaseByPackageManagerCountDto> releaseCounts = scaReleasesDao.countReleasesByPackageManager(db.getSession(), scaReleasesQuery); - assertThat(releaseCounts).hasSize(3); - assertThat(releaseCounts).extracting("packageManager", "releaseCount") - .containsExactlyInAnyOrder(Tuple.tuple(PackageManager.MAVEN.name(), 2), - Tuple.tuple(PackageManager.NPM.name(), 1), - Tuple.tuple(PackageManager.PYPI.name(), 1)); - } -} diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaReleasesDependenciesDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaReleasesDependenciesDaoIT.java deleted file mode 100644 index e8384f05a0c..00000000000 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaReleasesDependenciesDaoIT.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; -import org.sonar.db.component.ComponentDto; - -import static org.assertj.core.api.Assertions.assertThat; - -class ScaReleasesDependenciesDaoIT { - @RegisterExtension - private final DbTester db = DbTester.create(System2.INSTANCE); - - private final ScaReleasesDependenciesDao scaReleasesDependenciesDao = db.getDbClient().scaReleasesDependenciesDao(); - - @Test - void test_whenEmptyDatabaseAndQuery_selectByReleaseUuids() { - assertThat(scaReleasesDependenciesDao.selectByReleaseUuids(db.getSession(), List.of())).isEmpty(); - } - - @Test - void test_whenSomeDependencies_selectByReleaseUuids() { - ComponentDto componentDto = db.components().insertPublicProject().getMainBranchComponent(); - - ScaDependencyDto scaDependencyDto1a = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "1a", true, PackageManager.MAVEN, "foo.bar1"); - // same release, different dependency - ScaDependencyDto scaDependencyDto1b = db.getScaDependenciesDbTester().insertScaDependency(scaDependencyDto1a.scaReleaseUuid(), "1b", false); - ScaDependencyDto scaDependencyDto2 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "2", true, PackageManager.MAVEN, "foo.bar2"); - ScaDependencyDto scaDependencyDto3 = db.getScaDependenciesDbTester().insertScaDependencyWithRelease(componentDto.uuid(), "3", true, PackageManager.MAVEN, "foo.bar3"); - - List<ScaReleaseDependenciesDto> results = scaReleasesDependenciesDao.selectByReleaseUuids(db.getSession(), - List.of(scaDependencyDto1a.scaReleaseUuid(), scaDependencyDto2.scaReleaseUuid())); - - assertThat(results.stream().map(ScaReleaseDependenciesDto::dependencies).flatMap(List::stream).toList()) - .containsExactlyInAnyOrder(scaDependencyDto1a, scaDependencyDto1b, scaDependencyDto2) - .doesNotContain(scaDependencyDto3); - var twoDeps = results.stream().filter(rd -> rd.releaseUuid().equals(scaDependencyDto1a.scaReleaseUuid())) - .findFirst().map(ScaReleaseDependenciesDto::dependencies).orElseThrow(); - assertThat(twoDeps).containsExactlyInAnyOrder(scaDependencyDto1a, scaDependencyDto1b); - - var resultsWithEmptyQuery = scaReleasesDependenciesDao.selectByReleaseUuids(db.getSession(), List.of()); - assertThat(resultsWithEmptyQuery).isEmpty(); - } -} diff --git a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaVulnerabilityIssuesDaoIT.java b/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaVulnerabilityIssuesDaoIT.java deleted file mode 100644 index dbfbaf3d6d2..00000000000 --- a/server/sonar-db-dao/src/it/java/org/sonar/db/sca/ScaVulnerabilityIssuesDaoIT.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.math.BigDecimal; -import java.math.RoundingMode; -import java.util.List; -import java.util.Map; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.sonar.api.utils.System2; -import org.sonar.db.DbTester; - -import static org.assertj.core.api.Assertions.assertThat; - -class ScaVulnerabilityIssuesDaoIT { - - @RegisterExtension - private final DbTester db = DbTester.create(System2.INSTANCE); - - private final ScaVulnerabilityIssuesDao scaVulnerabilityIssuesDao = db.getDbClient().scaVulnerabilityIssuesDao(); - - private static final ScaVulnerabilityIssueDto newScaVulnerabilityIssueDto(String suffix) { - return new ScaVulnerabilityIssueDto("uuid" + suffix, ScaSeverity.INFO, List.of("cwe-" + suffix), new BigDecimal("7.1"), 1L, 2L); - } - - @Test - void insert_shouldPersistScaVulnerabilityIssues() { - ScaVulnerabilityIssueDto issueDto = newScaVulnerabilityIssueDto("1"); - scaVulnerabilityIssuesDao.insert(db.getSession(), issueDto); - - List<Map<String, Object>> select = db.select(db.getSession(), "select * from sca_vulnerability_issues"); - assertThat(select).hasSize(1); - Map<String, Object> stringObjectMap = select.get(0); - // we can't compare doubles, so it's hackin' time - var possibleDouble = stringObjectMap.get("cvss_score"); - if (possibleDouble instanceof Double d) { - stringObjectMap.put("cvss_score", BigDecimal.valueOf(d)); - } - assertThat(stringObjectMap).containsExactlyInAnyOrderEntriesOf( - Map.ofEntries( - Map.entry("uuid", issueDto.uuid()), - Map.entry("base_severity", issueDto.baseSeverity().name()), - Map.entry("cwe_ids", "[" + String.join(", ", issueDto.cweIds().stream().map(s -> "\"" + s + "\"").toList()) + "]"), - Map.entry("cvss_score", issueDto.cvssScore()), - Map.entry("created_at", issueDto.createdAt()), - Map.entry("updated_at", issueDto.updatedAt()))); - } - - @Test - void insert_canSaveNullCvssScore() { - ScaVulnerabilityIssueDto issueDtoNotNull = newScaVulnerabilityIssueDto("1"); - ScaVulnerabilityIssueDto issueDto = new ScaVulnerabilityIssueDto(issueDtoNotNull.uuid(), ScaSeverity.INFO, issueDtoNotNull.cweIds(), - null, issueDtoNotNull.createdAt(), issueDtoNotNull.updatedAt()); - - scaVulnerabilityIssuesDao.insert(db.getSession(), issueDto); - - var loadedOptional = scaVulnerabilityIssuesDao.selectByUuid(db.getSession(), issueDto.uuid()); - - assertThat(loadedOptional).contains(issueDto); - assertThat(loadedOptional.get().cvssScore()).isNull(); - } - - @Test - void insert_canSaveTenCvssScore() { - ScaVulnerabilityIssueDto issueDtoBase = newScaVulnerabilityIssueDto("1"); - ScaVulnerabilityIssueDto issueDto = new ScaVulnerabilityIssueDto(issueDtoBase.uuid(), ScaSeverity.INFO, - issueDtoBase.cweIds(), new BigDecimal("10.0"), issueDtoBase.createdAt(), issueDtoBase.updatedAt()); - assertThat(issueDto.cvssScore().scale()).isEqualTo(1); - - scaVulnerabilityIssuesDao.insert(db.getSession(), issueDto); - - // the different db backends are not consistent about actually keeping the scale - // so we have to fix it to be what we expect - var loadedOptionalScore = scaVulnerabilityIssuesDao.selectByUuid(db.getSession(), issueDto.uuid()) - .map(ScaVulnerabilityIssueDto::cvssScore) - .map(score -> score.setScale(1, RoundingMode.HALF_UP)); - - assertThat(loadedOptionalScore).contains(issueDto.cvssScore()); - } - - @Test - void selectByUuid_shouldLoadScaVulnerabilityIssue() { - ScaVulnerabilityIssueDto issueDto = newScaVulnerabilityIssueDto("1"); - scaVulnerabilityIssuesDao.insert(db.getSession(), issueDto); - - var loadedOptional = scaVulnerabilityIssuesDao.selectByUuid(db.getSession(), issueDto.uuid()); - - assertThat(loadedOptional).contains(issueDto); - } - - @Test - void selectByUuids_shouldLoadScaVulnerabilityIssues() { - List<ScaVulnerabilityIssueDto> issueDtos = List.of(newScaVulnerabilityIssueDto("1"), - newScaVulnerabilityIssueDto("2"), newScaVulnerabilityIssueDto("3")); - for (var issueDto : issueDtos) { - scaVulnerabilityIssuesDao.insert(db.getSession(), issueDto); - } - - List<String> uuidsToLoad = List.of(issueDtos.get(0).uuid(), issueDtos.get(2).uuid()); - var loaded = scaVulnerabilityIssuesDao.selectByUuids(db.getSession(), uuidsToLoad); - - assertThat(loaded).containsExactlyInAnyOrder(issueDtos.get(0), issueDtos.get(2)); - } - - @Test - void update_shouldModifyScaVulnerabilityIssue() { - ScaVulnerabilityIssueDto issueDto = newScaVulnerabilityIssueDto("1"); - scaVulnerabilityIssuesDao.insert(db.getSession(), issueDto); - ScaVulnerabilityIssueDto issueDtoUpdated = new ScaVulnerabilityIssueDto(issueDto.uuid(), - ScaSeverity.BLOCKER, - issueDto.cweIds().stream().map(s -> s + "-updated").toList(), - issueDto.cvssScore().add(new BigDecimal("1.3")), - issueDto.createdAt(), 5L); - - assertThat(issueDtoUpdated.baseSeverity()).isNotEqualTo(issueDto.baseSeverity()); - - scaVulnerabilityIssuesDao.update(db.getSession(), issueDtoUpdated); - - var loadedOptional = scaVulnerabilityIssuesDao.selectByUuid(db.getSession(), issueDto.uuid()); - - assertThat(loadedOptional).contains(issueDtoUpdated); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java index 23ee064c592..02986d9c4c6 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java @@ -88,13 +88,6 @@ import org.sonar.db.report.ReportSubscriptionDao; import org.sonar.db.rule.RuleChangeDao; import org.sonar.db.rule.RuleDao; import org.sonar.db.rule.RuleRepositoryDao; -import org.sonar.db.sca.ScaDependenciesDao; -import org.sonar.db.sca.ScaIssuesDao; -import org.sonar.db.sca.ScaIssuesReleasesDao; -import org.sonar.db.sca.ScaIssuesReleasesDetailsDao; -import org.sonar.db.sca.ScaReleasesDao; -import org.sonar.db.sca.ScaReleasesDependenciesDao; -import org.sonar.db.sca.ScaVulnerabilityIssuesDao; import org.sonar.db.scannercache.ScannerAnalysisCacheDao; import org.sonar.db.schemamigration.SchemaMigrationDao; import org.sonar.db.scim.ScimGroupDao; @@ -156,7 +149,6 @@ public class DaoModule extends Module { IssueChangeDao.class, IssueDao.class, IssueFixedDao.class, - ScaIssuesReleasesDetailsDao.class, MeasureDao.class, ProjectMeasureDao.class, MetricDao.class, @@ -192,12 +184,6 @@ public class DaoModule extends Module { RuleChangeDao.class, RuleRepositoryDao.class, SamlMessageIdDao.class, - ScaDependenciesDao.class, - ScaIssuesDao.class, - ScaIssuesReleasesDao.class, - ScaReleasesDao.class, - ScaReleasesDependenciesDao.class, - ScaVulnerabilityIssuesDao.class, ScannerAnalysisCacheDao.class, SchemaMigrationDao.class, ScimGroupDao.class, diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java index ed5319a5ec9..ec1fc6884b1 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java @@ -88,13 +88,6 @@ import org.sonar.db.report.ReportSubscriptionDao; import org.sonar.db.rule.RuleChangeDao; import org.sonar.db.rule.RuleDao; import org.sonar.db.rule.RuleRepositoryDao; -import org.sonar.db.sca.ScaDependenciesDao; -import org.sonar.db.sca.ScaIssuesDao; -import org.sonar.db.sca.ScaIssuesReleasesDao; -import org.sonar.db.sca.ScaIssuesReleasesDetailsDao; -import org.sonar.db.sca.ScaReleasesDao; -import org.sonar.db.sca.ScaReleasesDependenciesDao; -import org.sonar.db.sca.ScaVulnerabilityIssuesDao; import org.sonar.db.scannercache.ScannerAnalysisCacheDao; import org.sonar.db.schemamigration.SchemaMigrationDao; import org.sonar.db.scim.ScimGroupDao; @@ -207,13 +200,6 @@ public class DbClient { private final ProjectExportDao projectExportDao; private final IssueFixedDao issueFixedDao; private final TelemetryMetricsSentDao telemetryMetricsSentDao; - private final ScaReleasesDao scaReleasesDao; - private final ScaDependenciesDao scaDependenciesDao; - private final ScaReleasesDependenciesDao scaReleasesDependenciesDao; - private final ScaIssuesDao scaIssuesDao; - private final ScaIssuesReleasesDao scaIssuesReleasesDao; - private final ScaVulnerabilityIssuesDao scaVulnerabilityIssuesDao; - private final ScaIssuesReleasesDetailsDao scaIssuesReleasesDetailsDao; public DbClient(Database database, MyBatis myBatis, DBSessions dbSessions, Dao... daos) { this.database = database; @@ -310,13 +296,6 @@ public class DbClient { projectExportDao = getDao(map, ProjectExportDao.class); issueFixedDao = getDao(map, IssueFixedDao.class); telemetryMetricsSentDao = getDao(map, TelemetryMetricsSentDao.class); - scaReleasesDao = getDao(map, ScaReleasesDao.class); - scaDependenciesDao = getDao(map, ScaDependenciesDao.class); - scaReleasesDependenciesDao = getDao(map, ScaReleasesDependenciesDao.class); - scaIssuesDao = getDao(map, ScaIssuesDao.class); - scaIssuesReleasesDao = getDao(map, ScaIssuesReleasesDao.class); - scaVulnerabilityIssuesDao = getDao(map, ScaVulnerabilityIssuesDao.class); - scaIssuesReleasesDetailsDao = getDao(map, ScaIssuesReleasesDetailsDao.class); } public DbSession openSession(boolean batch) { @@ -680,32 +659,4 @@ public class DbClient { public ProjectExportDao projectExportDao() { return projectExportDao; } - - public ScaReleasesDao scaReleasesDao() { - return scaReleasesDao; - } - - public ScaDependenciesDao scaDependenciesDao() { - return scaDependenciesDao; - } - - public ScaReleasesDependenciesDao scaReleasesDependenciesDao() { - return scaReleasesDependenciesDao; - } - - public ScaIssuesDao scaIssuesDao() { - return scaIssuesDao; - } - - public ScaIssuesReleasesDao scaIssuesReleasesDao() { - return scaIssuesReleasesDao; - } - - public ScaVulnerabilityIssuesDao scaVulnerabilityIssuesDao() { - return scaVulnerabilityIssuesDao; - } - - public ScaIssuesReleasesDetailsDao scaIssuesReleasesDetailsDao() { - return scaIssuesReleasesDetailsDao; - } } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java index cb67f4a4b65..334ad5a5cdf 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java @@ -151,13 +151,6 @@ import org.sonar.db.rule.RuleChangeMapper; import org.sonar.db.rule.RuleMapper; import org.sonar.db.rule.RuleParamDto; import org.sonar.db.rule.RuleRepositoryMapper; -import org.sonar.db.sca.ScaDependenciesMapper; -import org.sonar.db.sca.ScaDependencyDto; -import org.sonar.db.sca.ScaIssuesMapper; -import org.sonar.db.sca.ScaIssuesReleasesDetailsMapper; -import org.sonar.db.sca.ScaIssuesReleasesMapper; -import org.sonar.db.sca.ScaReleasesMapper; -import org.sonar.db.sca.ScaVulnerabilityIssuesMapper; import org.sonar.db.scannercache.ScannerAnalysisCacheMapper; import org.sonar.db.schemamigration.SchemaMigrationDto; import org.sonar.db.schemamigration.SchemaMigrationMapper; @@ -258,7 +251,6 @@ public class MyBatis { confBuilder.loadAlias("QualityGate", QualityGateDto.class); confBuilder.loadAlias("Resource", ResourceDto.class); confBuilder.loadAlias("RuleParam", RuleParamDto.class); - confBuilder.loadAlias("ScaDependency", ScaDependencyDto.class); confBuilder.loadAlias("SchemaMigration", SchemaMigrationDto.class); confBuilder.loadAlias("ScrapProperty", ScrapPropertyDto.class); confBuilder.loadAlias("ScrapAnalysisProperty", ScrapAnalysisPropertyDto.class); @@ -347,12 +339,6 @@ public class MyBatis { RuleChangeMapper.class, RuleRepositoryMapper.class, SamlMessageIdMapper.class, - ScaDependenciesMapper.class, - ScaIssuesMapper.class, - ScaIssuesReleasesMapper.class, - ScaIssuesReleasesDetailsMapper.class, - ScaReleasesMapper.class, - ScaVulnerabilityIssuesMapper.class, ScannerAnalysisCacheMapper.class, SchemaMigrationMapper.class, ScimGroupMapper.class, diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/DefaultScaIssueIdentity.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/DefaultScaIssueIdentity.java deleted file mode 100644 index 7eec1512e71..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/DefaultScaIssueIdentity.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import static com.google.common.base.Preconditions.checkArgument; - -/** - * <p> - * Default implementation of {@link ScaIssueIdentity}. - * </p> - * <p> - * Caution: missing fields are empty string, not null, so db unique constraint works. - * </p> - * @param scaIssueType the issue type - * @param packageUrl the package url (may or may not have a version) - * @param vulnerabilityId the vulnerability id such as CVE-12345 - * @param spdxLicenseId the SPDX license identifier (not license expression) - */ -public record DefaultScaIssueIdentity(ScaIssueType scaIssueType, - String packageUrl, - String vulnerabilityId, - String spdxLicenseId) implements ScaIssueIdentity { - public DefaultScaIssueIdentity { - checkIdentityColumn(packageUrl, "packageUrl"); - checkIdentityColumn(vulnerabilityId, "vulnerabilityId"); - checkIdentityColumn(spdxLicenseId, "spdxLicenseId"); - } - - private static void checkIdentityColumn(String value, String name) { - checkArgument(value != null, "DefaultScaIssueIdentity.%s cannot be null", name); - checkArgument(!value.isBlank(), "DefaultScaIssueIdentity.%s cannot be blank, use ScaIssueDto.NULL_VALUE", name); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ListOfListOfStringsTypeHandler.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ListOfListOfStringsTypeHandler.java deleted file mode 100644 index e90ddafba5d..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ListOfListOfStringsTypeHandler.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import java.lang.reflect.Type; -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.List; -import org.apache.ibatis.type.BaseTypeHandler; -import org.apache.ibatis.type.JdbcType; - -public class ListOfListOfStringsTypeHandler extends BaseTypeHandler<List<List<String>>> { - private static final Gson GSON = new Gson(); - private static final Type type = new TypeToken<List<List<String>>>() { - }.getType(); - - @Override - public void setNonNullParameter(PreparedStatement ps, int i, List<List<String>> parameter, JdbcType jdbcType) throws SQLException { - ps.setString(i, GSON.toJson(parameter)); - } - - @Override - public List<List<String>> getNullableResult(ResultSet rs, String columnName) throws SQLException { - return GSON.fromJson(rs.getString(columnName), type); - } - - @Override - public List<List<String>> getNullableResult(ResultSet rs, int columnIndex) throws SQLException { - return GSON.fromJson(rs.getString(columnIndex), type); - } - - @Override - public List<List<String>> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { - return GSON.fromJson(cs.getString(columnIndex), type); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ListOfStringsTypeHandler.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ListOfStringsTypeHandler.java deleted file mode 100644 index 6d573e282d8..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ListOfStringsTypeHandler.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import java.lang.reflect.Type; -import java.sql.CallableStatement; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.List; -import org.apache.ibatis.type.BaseTypeHandler; -import org.apache.ibatis.type.JdbcType; - -public class ListOfStringsTypeHandler extends BaseTypeHandler<List<String>> { - public static final int MAXIMUM_LENGTH = 255; - private static final Gson GSON = new Gson(); - private static final Type type = new TypeToken<List<String>>() { - }.getType(); - - @Override - public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType) throws SQLException { - var s = GSON.toJson(parameter); - if (s.length() > MAXIMUM_LENGTH) { - throw new SQLException("List of strings is too long to store in database"); - } - ps.setString(i, s); - } - - @Override - public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException { - return GSON.fromJson(rs.getString(columnName), type); - } - - @Override - public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException { - return GSON.fromJson(rs.getString(columnIndex), type); - } - - @Override - public List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { - return GSON.fromJson(cs.getString(columnIndex), type); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/PackageManager.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/PackageManager.java deleted file mode 100644 index 50b49bcd185..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/PackageManager.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -/** - * These values come from https://github.com/package-url/purl-spec/blob/master/PURL-TYPES.rst and correspond - * to the package manager string used in PURLs. - */ -public enum PackageManager { - CARGO, COCOAPODS, COMPOSER, CONAN, CONDA, GEM, GOLANG, MAVEN, NPM, NUGET, PYPI -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependenciesDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependenciesDao.java deleted file mode 100644 index 166a8e0f2aa..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependenciesDao.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import org.sonar.db.Dao; -import org.sonar.db.DbSession; -import org.sonar.db.Pagination; - -public class ScaDependenciesDao implements Dao { - - private static ScaDependenciesMapper mapper(DbSession session) { - return session.getMapper(ScaDependenciesMapper.class); - } - - public void insert(DbSession session, ScaDependencyDto scaDependencyDto) { - mapper(session).insert(scaDependencyDto); - } - - public void deleteByUuid(DbSession session, String uuid) { - mapper(session).deleteByUuid(uuid); - } - - public Optional<ScaDependencyDto> selectByUuid(DbSession dbSession, String uuid) { - return Optional.ofNullable(mapper(dbSession).selectByUuid(uuid)); - } - - /** - * Retrieves all dependencies with a specific branch UUID, no other filtering is done by this method. - */ - public List<ScaDependencyDto> selectByBranchUuid(DbSession dbSession, String branchUuid) { - return mapper(dbSession).selectByBranchUuid(branchUuid); - } - - public List<ScaDependencyDto> selectByQuery(DbSession session, ScaDependenciesQuery scaDependenciesQuery, Pagination pagination) { - return mapper(session).selectByQuery(scaDependenciesQuery, pagination); - } - - public int countByQuery(DbSession session, ScaDependenciesQuery scaDependenciesQuery) { - return mapper(session).countByQuery(scaDependenciesQuery); - } - - public void update(DbSession session, ScaDependencyDto scaDependencyDto) { - mapper(session).update(scaDependencyDto); - } - - public List<ScaDependencyDto> selectByReleaseUuids(DbSession dbSession, Collection<String> releaseUuids) { - return mapper(dbSession).selectByReleaseUuids(releaseUuids); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependenciesMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependenciesMapper.java deleted file mode 100644 index 9113c76a906..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependenciesMapper.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.Collection; -import java.util.List; -import org.apache.ibatis.annotations.Param; -import org.sonar.db.Pagination; - -public interface ScaDependenciesMapper { - void insert(ScaDependencyDto dto); - - void deleteByUuid(String uuid); - - ScaDependencyDto selectByUuid(String uuid); - - List<ScaDependencyDto> selectByBranchUuid(String branchUuid); - - List<ScaDependencyDto> selectByQuery(@Param("query") ScaDependenciesQuery query, @Param("pagination") Pagination pagination); - - List<ScaDependencyDto> selectByReleaseUuids(Collection<String> releaseUuids); - - void update(ScaDependencyDto dto); - - int countByQuery(@Param("query") ScaDependenciesQuery query); -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependenciesQuery.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependenciesQuery.java deleted file mode 100644 index 459fcf7a50e..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependenciesQuery.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import java.util.Locale; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import static org.sonar.db.DaoUtils.buildLikeValue; -import static org.sonar.db.WildcardPosition.AFTER; - -public record ScaDependenciesQuery( - String branchUuid, - @Nullable Boolean direct, - @Nullable List<String> packageManagers, - @Nullable String query) { - - /** - * Used by MyBatis mapper - */ - @CheckForNull - public String likeQuery() { - return query == null ? null : buildLikeValue(query.toLowerCase(Locale.ENGLISH), AFTER); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependencyDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependencyDto.java deleted file mode 100644 index 2b5f59800bc..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependencyDto.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import com.google.gson.Gson; -import java.util.List; -import javax.annotation.Nullable; - -import static com.google.common.base.Preconditions.checkArgument; - -/** - * Represents a Software Composition Analysis (SCA) dependency, associated with a component. - * The component will be a package component nested inside a project branch component. - * <p> - * One of userDependencyFilePath or lockfileDependencyFilePath should not be null. - *</p> - * <p> - * A dependency is a "mention" of a release in a project, with a scope and a specific - * dependency file that it was mentioned in. - *</p> - * @param uuid primary key - * @param scaReleaseUuid the UUID of the SCA release that this dependency refers to - * @param direct is this a direct dependency of the project - * @param scope the scope of the dependency e.g. "development" - * @param productionScope whether the scope appears to be a production scope or test scope - * @param userDependencyFilePath path to the user-editable file where the dependency was found ("manifest") e.g. package.json - * @param lockfileDependencyFilePath path to the machine-maintained lockfile where the dependency was found e.g. package-lock.json - * @param chains a list of the purl chains that require the dependency, stored as JSON string, e.g. [["pkg:npm/foo@1.0.0", ...], ...] - * @param newInPullRequest is it newly-added vs. target branch in this PR - * @param createdAt timestamp of creation - * @param updatedAt timestamp of most recent update - */ -public record ScaDependencyDto( - String uuid, - String scaReleaseUuid, - boolean direct, - String scope, - boolean productionScope, - @Nullable String userDependencyFilePath, - @Nullable String lockfileDependencyFilePath, - @Nullable List<List<String>> chains, - boolean newInPullRequest, - long createdAt, - long updatedAt) { - - // These need to be in sync with the database but because the db migration module and this module don't - // depend on each other, we can't make one just refer to the other. - public static final int SCOPE_MAX_LENGTH = 100; - public static final int DEPENDENCY_FILE_PATH_MAX_LENGTH = 1000; - - private static final Gson GSON = new Gson(); - - public ScaDependencyDto { - // We want these to raise errors and not silently put junk values in the db - checkLength(scope, SCOPE_MAX_LENGTH, "scope"); - checkLength(userDependencyFilePath, DEPENDENCY_FILE_PATH_MAX_LENGTH, "userDependencyFilePath"); - checkLength(lockfileDependencyFilePath, DEPENDENCY_FILE_PATH_MAX_LENGTH, "lockfileDependencyFilePath"); - if (userDependencyFilePath == null && lockfileDependencyFilePath == null) { - throw new IllegalArgumentException("One of userDependencyFilePath or lockfileDependencyFilePath should not be null"); - } - } - - private static void checkLength(@Nullable String value, int maxLength, String name) { - if (value != null) { - checkArgument(value.length() <= maxLength, "Maximum length of %s is %s: %s", name, maxLength, value); - } - } - - public String getChainsJson() { - return chains == null ? null : GSON.toJson(chains); - } - - /** - * Returns the userDependencyFilePath if it is not null, otherwise returns the lockfileDependencyFilePath. - * - * @return a non-null file path - */ - public String primaryDependencyFilePath() { - return userDependencyFilePath != null ? userDependencyFilePath : lockfileDependencyFilePath; - } - - /** - * Returns an object whose .equals and .hashCode would match that of another ScaDependencyDto's - * identity() if the two ScaDependencyDto would count as duplicates within the sca_dependencies table. - * This is different from the DTOs themselves being equal because some fields do not count in - * the identity of the row, and can be updated while preserving the identity. The method just - * returns Object and not a type, because it exists just to call .equals and .hashCode on. - * - * @return an object to be used for hashing and comparing ScaDependencyDto instances for identity - */ - public Identity identity() { - return new IdentityImpl(this); - } - - public Builder toBuilder() { - return new Builder() - .setUuid(this.uuid) - .setScaReleaseUuid(this.scaReleaseUuid) - .setDirect(this.direct) - .setScope(this.scope) - .setProductionScope(this.productionScope) - .setUserDependencyFilePath(this.userDependencyFilePath) - .setLockfileDependencyFilePath(this.lockfileDependencyFilePath) - .setChains(this.chains) - .setNewInPullRequest(this.newInPullRequest) - .setCreatedAt(this.createdAt) - .setUpdatedAt(this.updatedAt); - } - - public interface Identity { - /** - * Return a new identity with a different scaReleaseUuid - * @param scaReleaseUuid to swap in to the identity - * @return an object to be used for hashing and comparing ScaDependencyDto instances for identity - */ - Identity withScaReleaseUuid(String scaReleaseUuid); - } - - /** This object has the subset of fields that have to be unique in a ScaDependencyDto, - * so if this is the same for two ScaDependencyDto, we can update rather than insert - * those ScaDependencyDto. Conceptually, sca_dependencies table could have a unique - * constraint on these fields, though in practice it does not. - *<p> - * This class is private because it is exclusively used for .equals and .hashCode - * so nobody cares about it otherwise. - *</p> - */ - private record IdentityImpl(String scaReleaseUuid, - boolean direct, - String scope, - @Nullable String userDependencyFilePath, - @Nullable String lockfileDependencyFilePath) implements Identity { - - IdentityImpl(ScaDependencyDto dto) { - this(dto.scaReleaseUuid(), dto.direct(), dto.scope(), dto.userDependencyFilePath(), dto.lockfileDependencyFilePath()); - } - - @Override - public IdentityImpl withScaReleaseUuid(String scaReleaseUuid) { - return new IdentityImpl(scaReleaseUuid, direct, scope, userDependencyFilePath, lockfileDependencyFilePath); - } - } - - public static class Builder { - private String uuid; - private String scaReleaseUuid; - private boolean direct; - private String scope; - private boolean productionScope; - private String userDependencyFilePath; - private String lockfileDependencyFilePath; - private List<List<String>> chains; - private boolean newInPullRequest; - private long createdAt; - private long updatedAt; - - public Builder setUuid(String uuid) { - this.uuid = uuid; - return this; - } - - public Builder setScaReleaseUuid(String scaReleaseUuid) { - this.scaReleaseUuid = scaReleaseUuid; - return this; - } - - public Builder setDirect(boolean direct) { - this.direct = direct; - return this; - } - - public Builder setScope(String scope) { - this.scope = scope; - return this; - } - - public Builder setProductionScope(boolean productionScope) { - this.productionScope = productionScope; - return this; - } - - public Builder setUserDependencyFilePath(@Nullable String dependencyFilePath) { - this.userDependencyFilePath = dependencyFilePath; - return this; - } - - public Builder setLockfileDependencyFilePath(@Nullable String dependencyFilePath) { - this.lockfileDependencyFilePath = dependencyFilePath; - return this; - } - - public Builder setChains(@Nullable List<List<String>> chains) { - this.chains = chains; - return this; - } - - public Builder setNewInPullRequest(boolean newInPullRequest) { - this.newInPullRequest = newInPullRequest; - return this; - } - - public Builder setCreatedAt(long createdAt) { - this.createdAt = createdAt; - return this; - } - - public Builder setUpdatedAt(long updatedAt) { - this.updatedAt = updatedAt; - return this; - } - - public ScaDependencyDto build() { - return new ScaDependencyDto( - uuid, scaReleaseUuid, direct, scope, productionScope, userDependencyFilePath, lockfileDependencyFilePath, chains, newInPullRequest, createdAt, updatedAt); - } - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependencyReleaseDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependencyReleaseDto.java deleted file mode 100644 index 131a84bf1c0..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaDependencyReleaseDto.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import javax.annotation.Nullable; - -/** - * This DTO represents the join of sca_dependencies and sca_releases, and is "read only" - * (it cannot be inserted, it would only be a query result). - * - * @param dependencyUuid uuid of the sca_dependencies row - * @param releaseUuid uuid of the sca_releases row - * @param componentUuid uuid of the component both rows were associated with - * @param direct is it a direct dep - * @param scope scope/type of the dep like "compile" - * @param userDependencyFilePath which manifest file (e.g. package.json) - * @param lockfileDependencyFilePath which lockfile (e.g. package-lock.json) - * @param chains chains that brought the dependency in, e.g. [["pkg:npm/foo@1.0.0", ...], ...] - * @param packageUrl PURL specification URL - * @param packageManager package manager - * @param packageName name of package - * @param version version - * @param licenseExpression SPDX license expression - * @param known was the package known to Sonar - */ -public record ScaDependencyReleaseDto(String dependencyUuid, - String releaseUuid, - String componentUuid, - boolean direct, - String scope, - @Nullable String userDependencyFilePath, - @Nullable String lockfileDependencyFilePath, - @Nullable List<List<String>> chains, - String packageUrl, - PackageManager packageManager, - String packageName, - String version, - String licenseExpression, - boolean known) { - - public ScaDependencyReleaseDto(ScaDependencyDto dependency, ScaReleaseDto release) { - this( - dependency.uuid(), - release.uuid(), - release.componentUuid(), - dependency.direct(), - dependency.scope(), - dependency.userDependencyFilePath(), - dependency.lockfileDependencyFilePath(), - dependency.chains(), - release.packageUrl(), - release.packageManager(), - release.packageName(), - release.version(), - release.licenseExpression(), - release.known()); - if (!dependency.scaReleaseUuid().equals(release.uuid())) { - throw new IllegalArgumentException("Dependency and release UUIDs should match"); - } - } - - public String primaryDependencyFilePath() { - return userDependencyFilePath != null ? userDependencyFilePath : lockfileDependencyFilePath; - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueDto.java deleted file mode 100644 index c1d28a4916b..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueDto.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import static com.google.common.base.Preconditions.checkArgument; - -/** - * This table has GLOBAL rows spanning all analysis runs. For a given notional - * problem there will be ONE row. A notional problem could be a particular - * vulnerability "CVE-12345" or a particular license rule like "GPL-3.0 is prohibited". - * The purpose of this table is to assign a uuid to that notional problem. - * Because the uuid must be globally unique for the same problem, there is a - * unique constraint across all the columns. - * <p> - * NULL columns cannot participate in unique constraints on all database backends, - * so irrelevant columns for a particular issue type are set to empty string instead of NULL. - * </p> - * <p> - * The columns in this table should be those that establish the identity of the issue - * and no more. See {@link ScaIssueType} which has a method returning the proper - * ScaIssueDto for each issue type. Those same columns without uuid and timestamps - * are also in the {@link DefaultScaIssueIdentity} type. - * </p> - * <p> - * The packageUrl may or may not include a version number, depending on whether - * the issue type is per-package or per-release. - * </p> - */ -public record ScaIssueDto( - String uuid, - ScaIssueType scaIssueType, - String packageUrl, - String vulnerabilityId, - String spdxLicenseId, - long createdAt, - long updatedAt) implements ScaIssueIdentity { - - /** - * Value that represents "does not apply" in one of the identity columns. - * <p> - * You know you are going to ask, so the reason we can't use empty string - * is that Oracle thinks empty strings are NULL. And the reason we can't - * use NULL is that not all databases have a way to consider NULL as a - * value in a unique constraint. So anyway, just go with it. - * </p> - * <p> - * This string should be invalid as an actual value for all of the - * columns, so it's not a package url, not a vulnerability ID, - * and not a SPDX license ID. - * </p> - */ - public static final String NULL_VALUE = "-"; - - // these need to match what's in the db - public static final int SCA_ISSUE_TYPE_MAX_LENGTH = 40; - public static final int PACKAGE_URL_MAX_LENGTH = 400; - public static final int VULNERABILITY_ID_MAX_LENGTH = 63; - public static final int SPDX_LICENSE_ID_MAX_LENGTH = 127; - - public ScaIssueDto { - // We want these to raise errors and not silently put junk values in the db - checkIdentityColumn(packageUrl, PACKAGE_URL_MAX_LENGTH, "packageUrl"); - checkIdentityColumn(vulnerabilityId, VULNERABILITY_ID_MAX_LENGTH, "vulnerabilityId"); - checkIdentityColumn(spdxLicenseId, SPDX_LICENSE_ID_MAX_LENGTH, "spdxLicenseId"); - } - - public ScaIssueDto(String uuid, ScaIssueIdentity identity, long createdAt, long updatedAt) { - this(uuid, identity.scaIssueType(), identity.packageUrl(), identity.vulnerabilityId(), identity.spdxLicenseId(), createdAt, updatedAt); - } - - private static void checkIdentityColumn(String value, int maxLength, String name) { - checkArgument(value != null, "Column %s cannot be null", name); - checkArgument(!value.isBlank(), "Column %s cannot be blank, use ScaIssueDto.NULL_VALUE", name); - checkArgument(value.length() <= maxLength, "Maximum length of %s is %s: %s", name, maxLength, value); - } - - public Builder toBuilder() { - return new Builder() - .setUuid(uuid) - .setScaIssueType(scaIssueType) - .setPackageUrl(packageUrl) - .setVulnerabilityId(vulnerabilityId) - .setSpdxLicenseId(spdxLicenseId) - .setCreatedAt(createdAt) - .setUpdatedAt(updatedAt); - } - - public static class Builder { - private String uuid; - private ScaIssueType scaIssueType; - private String packageUrl; - private String vulnerabilityId; - private String spdxLicenseId; - private long createdAt; - private long updatedAt; - - public Builder setUuid(String uuid) { - this.uuid = uuid; - return this; - } - - public Builder setScaIssueType(ScaIssueType scaIssueType) { - this.scaIssueType = scaIssueType; - return this; - } - - public Builder setPackageUrl(String packageUrl) { - this.packageUrl = packageUrl; - return this; - } - - public Builder setVulnerabilityId(String vulnerabilityId) { - this.vulnerabilityId = vulnerabilityId; - return this; - } - - public Builder setSpdxLicenseId(String spdxLicenseId) { - this.spdxLicenseId = spdxLicenseId; - return this; - } - - public Builder setCreatedAt(long createdAt) { - this.createdAt = createdAt; - return this; - } - - public Builder setUpdatedAt(long updatedAt) { - this.updatedAt = updatedAt; - return this; - } - - public ScaIssueDto build() { - return new ScaIssueDto(uuid, scaIssueType, packageUrl, vulnerabilityId, spdxLicenseId, createdAt, updatedAt); - } - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueIdentity.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueIdentity.java deleted file mode 100644 index fc101ea46f6..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueIdentity.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -/** - * <p> - * Contains those fields which are in the unique index of the sca_issues table. - * This will be a subset of fields in the {@link ScaIssueDto} class. - * These fields are used to assign a global uuid to each issue, such as - * each vulnerability or each prohibited license. - * </p> - * <p> - * None of the fields are nullable; if not relevant to the issue's identity - * they must be empty string instead. Nulls are not usable in a unique index - * in standard sql. - * </p> - * <p> - * Implementations of this interface are allowed to include fields other than - * the identity fields in their equals and hashCode, so it is probably not - * appropriate to use instances of this interface as a hash key. You can likely - * use a concrete implementation of this interface as a hash key, though. - * </p> - */ -public interface ScaIssueIdentity { - ScaIssueType scaIssueType(); - - String packageUrl(); - - String vulnerabilityId(); - - String spdxLicenseId(); -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueReleaseDetailsDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueReleaseDetailsDto.java deleted file mode 100644 index 5ea5e9f49a1..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueReleaseDetailsDto.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.math.BigDecimal; -import java.util.List; -import javax.annotation.Nullable; -import org.sonar.api.utils.DateUtils; - -/** - * <p>A "read-only" DTO used to query the join of sca_issues_releases, sca_issues, and sca_*_issues. - * This is used to return all the details shown in a list of issues in the UX. - * This DTO and its mapper are an optimization, to do more work in SQL and - * avoid "joining in Java." - * </p> - * <p> - * The uuids in the DTOs must all correspond, or some kind of bug is happening. - * </p> - * <p> - * issueReleaseUuid is passed in separately because it allows mybatis to have an ID for the DTO, - * which it then uses for caching and lookup instead of hashing the whole object. - * </p> - */ -public record ScaIssueReleaseDetailsDto( - String issueReleaseUuid, - ScaIssueReleaseDto issueReleaseDto, - ScaIssueDto issueDto, - ScaReleaseDto releaseDto, - @Nullable ScaVulnerabilityIssueDto vulnerabilityIssueDto) { - - public ScaIssueReleaseDetailsDto { - // the issueReleaseUuid is separate so mybatis can use it for instance - // identity, but it must match the UUID in the issueReleaseDto - // and is straight-up redundant. - if (!issueReleaseUuid.equals(issueReleaseDto.uuid())) { - throw new IllegalArgumentException("issueReleaseUuid must match issueReleaseDto.uuid()"); - } - if (!issueDto.uuid().equals(issueReleaseDto.scaIssueUuid())) { - throw new IllegalArgumentException("issueDto.uuid() must match issueReleaseDto.scaIssueUuid()"); - } - if (!releaseDto.uuid().equals(issueReleaseDto.scaReleaseUuid())) { - throw new IllegalArgumentException("releaseDto.uuid() must match issueReleaseDto.scaReleaseUuid()"); - } - if (vulnerabilityIssueDto != null && !vulnerabilityIssueDto.uuid().equals(issueDto.uuid())) { - throw new IllegalArgumentException("vulnerabilityIssueDto.uuid() must match issueDto.uuid()"); - } - } - - // DateUtils says that this returns an RFC 822 timestamp - // but it is really a ISO 8601 timestamp. - public String createdAtIso8601() { - return DateUtils.formatDateTime(issueReleaseDto.createdAt()); - } - - public ScaSeverity severity() { - return issueReleaseDto.severity(); - } - - public String issueUuid() { - return issueDto.uuid(); - } - - public String releaseUuid() { - return releaseDto.uuid(); - } - - public ScaIssueType scaIssueType() { - return issueDto.scaIssueType(); - } - - public boolean newInPullRequest() { - return releaseDto.newInPullRequest(); - } - - public String version() { - return releaseDto.version(); - } - - /** - * Returns the versioned package URL of the release - */ - public String releasePackageUrl() { - return releaseDto.packageUrl(); - } - - /** Returns the unversioned package URL of the security vulnerability, - * or ScaIssueDto::NULL_VALUE if the issue is not a vulnerability. - */ - public String issuePackageUrl() { - return issueDto.packageUrl(); - } - - /** - * Returns the vulnerability ID of the issue, or ScaIssueDto::NULL_VALUE if the issue is not a vulnerability. - */ - public String vulnerabilityId() { - return issueDto.vulnerabilityId(); - } - - /** Returns the SPDX license ID of the issue, or ScaIssueDto::NULL_VALUE if the issue is not a license issue. */ - public String spdxLicenseId() { - return issueDto.spdxLicenseId(); - } - - /** Returns the base severity of the vulnerability, or null if the issue is not a vulnerability. */ - public @Nullable ScaSeverity vulnerabilityBaseSeverity() { - return vulnerabilityIssueDto == null ? null : vulnerabilityIssueDto.baseSeverity(); - } - - /** Returns the CWE IDs of the vulnerability, or null if the issue is not a vulnerability. */ - public @Nullable List<String> cweIds() { - return vulnerabilityIssueDto == null ? null : vulnerabilityIssueDto.cweIds(); - } - - /** Returns the CVSS score of the vulnerability, or null if the issue is not a vulnerability or does not have a CVSS score. */ - public @Nullable BigDecimal cvssScore() { - return vulnerabilityIssueDto == null ? null : vulnerabilityIssueDto.cvssScore(); - } - - public Builder toBuilder() { - return new Builder() - .setIssueReleaseDto(issueReleaseDto) - .setIssueDto(issueDto) - .setReleaseDto(releaseDto) - .setVulnerabilityIssueDto(vulnerabilityIssueDto); - } - - public static class Builder { - private ScaIssueReleaseDto issueReleaseDto; - private ScaIssueDto issueDto; - private ScaReleaseDto releaseDto; - @Nullable - private ScaVulnerabilityIssueDto vulnerabilityIssueDto; - - public Builder setIssueReleaseDto(ScaIssueReleaseDto issueReleaseDto) { - this.issueReleaseDto = issueReleaseDto; - return this; - } - - public Builder setIssueDto(ScaIssueDto issueDto) { - this.issueDto = issueDto; - return this; - } - - public Builder setReleaseDto(ScaReleaseDto releaseDto) { - this.releaseDto = releaseDto; - return this; - } - - public Builder setVulnerabilityIssueDto(@Nullable ScaVulnerabilityIssueDto vulnerabilityIssueDto) { - this.vulnerabilityIssueDto = vulnerabilityIssueDto; - return this; - } - - public ScaIssueReleaseDetailsDto build() { - return new ScaIssueReleaseDetailsDto(issueReleaseDto.uuid(), issueReleaseDto, issueDto, releaseDto, vulnerabilityIssueDto); - } - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueReleaseDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueReleaseDto.java deleted file mode 100644 index 74f4979b0fa..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueReleaseDto.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -/** - * Represents a many-to-many join between Software Composition Analysis (SCA) issue and a SCA release. - * - * @param uuid primary key - * @param scaIssueUuid the UUID of the SCA issue - * @param scaReleaseUuid the UUID of the SCA release - * @param severity the severity of the issue - * @param createdAt timestamp of creation - * @param updatedAt timestamp of most recent update - */ -public record ScaIssueReleaseDto( - String uuid, - String scaIssueUuid, - String scaReleaseUuid, - ScaSeverity severity, - long createdAt, - long updatedAt) { - - /** - * This constructor makes it a little harder to get the issue and release uuids backward, - * if you have the DTOs around to use it. - */ - public ScaIssueReleaseDto(String uuid, ScaIssueDto scaIssueDto, ScaReleaseDto scaReleaseDto, ScaSeverity severity, long createdAt, long updatedAt) { - this(uuid, scaIssueDto.uuid(), scaReleaseDto.uuid(), severity, createdAt, updatedAt); - } - - public int severitySortKey() { - return severity.databaseSortKey(); - } - - public Builder toBuilder() { - return new Builder() - .setUuid(this.uuid) - .setScaIssueUuid(this.scaIssueUuid) - .setScaReleaseUuid(this.scaReleaseUuid) - .setSeverity(this.severity) - .setCreatedAt(this.createdAt) - .setUpdatedAt(this.updatedAt); - } - - /** - * Returns an object whose .equals and .hashCode would match that of another ScaIssueReleaseDto's - * identity() if the two ScaIssueReleaseDto would count as duplicates within the sca_issues_releases - * table. - * This is different from the DTOs themselves being equal because some fields do not count in - * the identity of the row, and can be updated while preserving the identity. The method just - * returns Object and not a type, because it exists just to call .equals and .hashCode on. - * - * @return an object to be used for hashing and comparing ScaReleaseDto instances for identity - */ - public Identity identity() { - return new IdentityImpl(this); - } - - public interface Identity { - } - - private record IdentityImpl(String scaIssueUuid, String scaReleaseUuid) implements Identity { - IdentityImpl(ScaIssueReleaseDto dto) { - this(dto.scaIssueUuid(), dto.scaReleaseUuid()); - } - } - - public static class Builder { - private String uuid; - private String scaIssueUuid; - private String scaReleaseUuid; - private ScaSeverity severity; - private long createdAt; - private long updatedAt; - - public Builder setUuid(String uuid) { - this.uuid = uuid; - return this; - } - - public Builder setScaIssueUuid(String scaIssueUuid) { - this.scaIssueUuid = scaIssueUuid; - return this; - } - - public Builder setScaReleaseUuid(String scaReleaseUuid) { - this.scaReleaseUuid = scaReleaseUuid; - return this; - } - - public Builder setSeverity(ScaSeverity severity) { - this.severity = severity; - return this; - } - - public Builder setCreatedAt(long createdAt) { - this.createdAt = createdAt; - return this; - } - - public Builder setUpdatedAt(long updatedAt) { - this.updatedAt = updatedAt; - return this; - } - - public ScaIssueReleaseDto build() { - return new ScaIssueReleaseDto( - uuid, scaIssueUuid, scaReleaseUuid, severity, createdAt, updatedAt); - } - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueType.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueType.java deleted file mode 100644 index 0dcd8825622..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssueType.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -/** - * The type of ScaIssue (not the type of generic Sonar issue). - */ -public enum ScaIssueType { - VULNERABILITY, - PROHIBITED_LICENSE; -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesDao.java deleted file mode 100644 index 93c527cff7a..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesDao.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import org.sonar.db.Dao; -import org.sonar.db.DbSession; - -public class ScaIssuesDao implements Dao { - - private static ScaIssuesMapper mapper(DbSession session) { - return session.getMapper(ScaIssuesMapper.class); - } - - public void insert(DbSession session, ScaIssueDto scaIssueDto) { - mapper(session).insert(scaIssueDto); - } - - public Optional<ScaIssueDto> selectByUuid(DbSession dbSession, String uuid) { - return Optional.ofNullable(mapper(dbSession).selectByUuid(uuid)); - } - - public List<ScaIssueDto> selectByUuids(DbSession dbSession, Collection<String> uuids) { - return mapper(dbSession).selectByUuids(uuids); - } - - public Optional<String> selectUuidByValue(DbSession dbSession, ScaIssueIdentity scaIssueIdentity) { - return mapper(dbSession).selectUuidByValue(scaIssueIdentity); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesMapper.java deleted file mode 100644 index 0ebe2c02056..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesMapper.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.Collection; -import java.util.List; -import java.util.Optional; - -public interface ScaIssuesMapper { - void insert(ScaIssueDto dto); - - ScaIssueDto selectByUuid(String uuid); - - List<ScaIssueDto> selectByUuids(Collection<String> uuids); - - Optional<String> selectUuidByValue(ScaIssueIdentity scaIssueIdentity); -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDao.java deleted file mode 100644 index 710deb12d2c..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDao.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import org.sonar.db.Dao; -import org.sonar.db.DbSession; - -public class ScaIssuesReleasesDao implements Dao { - - private static ScaIssuesReleasesMapper mapper(DbSession session) { - return session.getMapper(ScaIssuesReleasesMapper.class); - } - - public void insert(DbSession session, ScaIssueReleaseDto scaIssueReleaseDto) { - mapper(session).insert(scaIssueReleaseDto); - } - - public void update(DbSession session, ScaIssueReleaseDto scaIssueReleaseDto) { - mapper(session).update(scaIssueReleaseDto); - } - - public void deleteByUuid(DbSession session, String uuid) { - mapper(session).deleteByUuid(uuid); - } - - public List<ScaIssueReleaseDto> selectByBranchUuid(DbSession dbSession, String branchUuid) { - return mapper(dbSession).selectByBranchUuid(branchUuid); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDetailsDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDetailsDao.java deleted file mode 100644 index 31a0d5dd611..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDetailsDao.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import org.sonar.db.Dao; -import org.sonar.db.DbSession; -import org.sonar.db.Pagination; - -public class ScaIssuesReleasesDetailsDao implements Dao { - - private static ScaIssuesReleasesDetailsMapper mapper(DbSession session) { - return session.getMapper(ScaIssuesReleasesDetailsMapper.class); - } - - /** - * Retrieves all issues with a specific branch UUID, no other filtering is done by this method. - */ - public List<ScaIssueReleaseDetailsDto> selectByBranchUuid(DbSession dbSession, String branchUuid, Pagination pagination) { - return mapper(dbSession).selectByBranchUuid(branchUuid, pagination); - } - - /** - * Retrieves all issues with a specific release UUID, no other filtering is done by this method. - */ - public List<ScaIssueReleaseDetailsDto> selectByReleaseUuid(DbSession dbSession, String releaseUuid) { - return mapper(dbSession).selectByReleaseUuid(releaseUuid); - } - - /** - * Counts all issues with a specific branch UUID, no other filtering is done by this method. - */ - public int countByBranchUuid(DbSession dbSession, String branchUuid) { - return mapper(dbSession).countByBranchUuid(branchUuid); - } - - public List<ScaIssueReleaseDetailsDto> selectByQuery(DbSession dbSession, ScaIssuesReleasesDetailsQuery query, Pagination pagination) { - return mapper(dbSession).selectByQuery(query, pagination); - } - - public int countByQuery(DbSession dbSession, ScaIssuesReleasesDetailsQuery query) { - return mapper(dbSession).countByQuery(query); - } - - /** - * Retrieves a single issue with a specific release. - */ - public ScaIssueReleaseDetailsDto selectByScaIssueReleaseUuid(DbSession dbSession, String scaIssueReleaseUuid) { - return mapper(dbSession).selectByScaIssueReleaseUuid(scaIssueReleaseUuid); - } - -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDetailsMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDetailsMapper.java deleted file mode 100644 index 35d6608322d..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDetailsMapper.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import org.apache.ibatis.annotations.Param; -import org.sonar.db.Pagination; - -public interface ScaIssuesReleasesDetailsMapper { - List<ScaIssueReleaseDetailsDto> selectByBranchUuid(@Param("branchUuid") String branchUuid, @Param("pagination") Pagination pagination); - - ScaIssueReleaseDetailsDto selectByScaIssueReleaseUuid(String scaIssueReleaseUuid); - - List<ScaIssueReleaseDetailsDto> selectByReleaseUuid(String releaseUuid); - - int countByBranchUuid(String branchUuid); - - List<ScaIssueReleaseDetailsDto> selectByQuery(@Param("query") ScaIssuesReleasesDetailsQuery query, @Param("pagination") Pagination pagination); - - int countByQuery(@Param("query") ScaIssuesReleasesDetailsQuery query); -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDetailsQuery.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDetailsQuery.java deleted file mode 100644 index 17397e97c34..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesDetailsQuery.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import java.util.Locale; -import java.util.Objects; -import java.util.Optional; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import org.sonar.db.WildcardPosition; - -import static org.sonar.db.DaoUtils.buildLikeValue; -import static org.sonar.db.WildcardPosition.BEFORE_AND_AFTER; - -public record ScaIssuesReleasesDetailsQuery( - String branchUuid, - Sort sort, - @Nullable Boolean direct, - @Nullable Boolean productionScope, - @Nullable String vulnerabilityIdSubstring, - @Nullable String packageNameSubstring, - @Nullable Boolean newInPullRequest, - @Nullable List<ScaIssueType> types, - @Nullable List<ScaSeverity> severities, - @Nullable List<PackageManager> packageManagers) { - - public ScaIssuesReleasesDetailsQuery { - Objects.requireNonNull(branchUuid); - Objects.requireNonNull(sort); - } - - /** For use in the mapper after <code>upper(vulnerabilityId) LIKE</code>, - * and per the {@link org.sonar.db.DaoUtils#buildLikeValue(String, WildcardPosition)}} - * docs, we have to say <code>ESCAPE '/'</code>. We are using uppercase because - * most ids will be uppercase already. - */ - @CheckForNull - public String vulnerabilityIdUppercaseEscapedAsLikeValue() { - return vulnerabilityIdSubstring == null ? null : buildLikeValue(vulnerabilityIdSubstring.toUpperCase(Locale.ROOT), BEFORE_AND_AFTER); - } - - /** For use in the mapper after <code>lower(packageName) LIKE</code>, - * and per the {@link org.sonar.db.DaoUtils#buildLikeValue(String, WildcardPosition)}} - * docs, we have to say <code>ESCAPE '/'</code>. We are using lowercase because most - * package names will be all or mostly lowercase already. - */ - @CheckForNull - public String packageNameLowercaseEscapedAsLikeValue() { - return packageNameSubstring == null ? null : buildLikeValue(packageNameSubstring.toLowerCase(Locale.ROOT), BEFORE_AND_AFTER); - } - - public Builder toBuilder() { - return new Builder() - .setBranchUuid(branchUuid) - .setSort(sort) - .setDirect(direct) - .setProductionScope(productionScope) - .setVulnerabilityIdSubstring(vulnerabilityIdSubstring) - .setPackageNameSubstring(packageNameSubstring) - .setNewInPullRequest(newInPullRequest) - .setTypes(types) - .setSeverities(severities) - .setPackageManagers(packageManagers); - } - - public enum Sort { - IDENTITY_ASC("+identity"), - IDENTITY_DESC("-identity"), - SEVERITY_ASC("+severity"), - SEVERITY_DESC("-severity"), - CVSS_SCORE_ASC("+cvssScore"), - CVSS_SCORE_DESC("-cvssScore"); - - private final String queryParameterValue; - - Sort(String queryParameterValue) { - this.queryParameterValue = queryParameterValue; - } - - /** - * Convert a query parameter value to the corresponding {@link Sort} enum value. - * The passed-in string must not be null. - */ - public static Optional<Sort> fromQueryParameterValue(String queryParameterValue) { - for (Sort sort : values()) { - if (sort.queryParameterValue.equals(queryParameterValue)) { - return Optional.of(sort); - } - } - return Optional.empty(); - } - - public String queryParameterValue() { - return queryParameterValue; - } - } - - public static class Builder { - private String branchUuid; - private Sort sort; - private Boolean direct; - private Boolean productionScope; - private String vulnerabilityIdSubstring; - private String packageNameSubstring; - private Boolean newInPullRequest; - private List<ScaIssueType> types; - private List<ScaSeverity> severities; - private List<PackageManager> packageManagers; - - public Builder setBranchUuid(String branchUuid) { - this.branchUuid = branchUuid; - return this; - } - - public Builder setSort(Sort sort) { - this.sort = sort; - return this; - } - - public Builder setDirect(@Nullable Boolean direct) { - this.direct = direct; - return this; - } - - public Builder setProductionScope(@Nullable Boolean productionScope) { - this.productionScope = productionScope; - return this; - } - - public Builder setVulnerabilityIdSubstring(@Nullable String vulnerabilityIdSubstring) { - this.vulnerabilityIdSubstring = vulnerabilityIdSubstring; - return this; - } - - public Builder setPackageNameSubstring(@Nullable String packageNameSubstring) { - this.packageNameSubstring = packageNameSubstring; - return this; - } - - public Builder setNewInPullRequest(@Nullable Boolean newInPullRequest) { - this.newInPullRequest = newInPullRequest; - return this; - } - - public Builder setTypes(@Nullable List<ScaIssueType> types) { - this.types = types; - return this; - } - - public Builder setSeverities(@Nullable List<ScaSeverity> severities) { - this.severities = severities; - return this; - } - - public Builder setPackageManagers(@Nullable List<PackageManager> packageManagers) { - this.packageManagers = packageManagers; - return this; - } - - public ScaIssuesReleasesDetailsQuery build() { - return new ScaIssuesReleasesDetailsQuery(branchUuid, sort, direct, productionScope, vulnerabilityIdSubstring, - packageNameSubstring, newInPullRequest, types, severities, packageManagers); - } - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesMapper.java deleted file mode 100644 index 58c40fd1435..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaIssuesReleasesMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; - -public interface ScaIssuesReleasesMapper { - void insert(ScaIssueReleaseDto dto); - - void update(ScaIssueReleaseDto dto); - - void deleteByUuid(String uuid); - - List<ScaIssueReleaseDto> selectByBranchUuid(String branchUuid); -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleaseByPackageManagerCountDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleaseByPackageManagerCountDto.java deleted file mode 100644 index 35f2625f7c2..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleaseByPackageManagerCountDto.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -public record ScaReleaseByPackageManagerCountDto(String packageManager, int releaseCount) { -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleaseDependenciesDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleaseDependenciesDto.java deleted file mode 100644 index 82204443c5a..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleaseDependenciesDto.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import java.util.Objects; - -/** - * This DTO represents the join of sca_releases and sca_dependencies, and is "read only" - * (it cannot be inserted, it would only be a query result). - * <p> - * The releaseUuid must match the uuid in the release DTO, it is duplicated to help out mybatis - * in caching and lookup (allow the mapper for this DTO have an idArg). - * </p> - * @param releaseUuid uuid of the releaseDto - * @param release release - * @param dependencies dependency DTOs - */ -public record ScaReleaseDependenciesDto( - String releaseUuid, - ScaReleaseDto release, - List<ScaDependencyDto> dependencies) { - - public ScaReleaseDependenciesDto { - Objects.requireNonNull(release); - Objects.requireNonNull(dependencies); - if (!releaseUuid.equals(release.uuid())) { - throw new IllegalArgumentException("releaseUuid must match release.uuid()"); - } - } - - public ScaReleaseDependenciesDto(ScaReleaseDto release, List<ScaDependencyDto> dependencies) { - this(release.uuid(), release, dependencies); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleaseDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleaseDto.java deleted file mode 100644 index 0a7916383db..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleaseDto.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import static com.google.common.base.Preconditions.checkArgument; - -/** - * Represents a single release of a package, such as an npm or maven package, - * as found in a single dependency analysis run (so it's attached to a branch component, - * and there's a separate copy of each release per branch it appears in). - * - * @param uuid Primary key - * @param componentUuid the component the release is associated with - * @param packageUrl package URL following the PURL specification - * @param packageManager package manager e.g. PYPI - * @param packageName package name e.g. "urllib3" - * @param version package version e.g. "1.25.6" - * @param licenseExpression an SPDX license expression (NOT a single license, can have parens/AND/OR) - * @param declaredLicenseExpression the valid SPDX license expression declared by the package itself - * @param known is this package and version known to Sonar (if not it be internal, could be malicious, could be from a weird repo) - * @param newInPullRequest is it newly added in a PR (always false when not on a PR) - * @param createdAt timestamp it was created - * @param updatedAt timestamp it was last updated - */ -public record ScaReleaseDto( - String uuid, - String componentUuid, - String packageUrl, - PackageManager packageManager, - String packageName, - String version, - String licenseExpression, - String declaredLicenseExpression, - boolean known, - boolean newInPullRequest, - long createdAt, - long updatedAt) { - - // these need to match what's in the db - public static final int PACKAGE_URL_MAX_LENGTH = 400; - public static final int PACKAGE_MANAGER_MAX_LENGTH = 20; - public static final int PACKAGE_NAME_MAX_LENGTH = 400; - public static final int VERSION_MAX_LENGTH = 400; - public static final int LICENSE_EXPRESSION_MAX_LENGTH = 400; - - public ScaReleaseDto { - // We want these to raise errors and not silently put junk values in the db - checkLength(packageUrl, PACKAGE_URL_MAX_LENGTH, "packageUrl"); - checkLength(packageName, PACKAGE_NAME_MAX_LENGTH, "packageName"); - checkLength(version, VERSION_MAX_LENGTH, "version"); - checkLength(licenseExpression, LICENSE_EXPRESSION_MAX_LENGTH, "licenseExpression"); - } - - private static void checkLength(String value, int maxLength, String name) { - checkArgument(value.length() <= maxLength, "Maximum length of %s is %s: %s", name, maxLength, value); - } - - public Builder toBuilder() { - return new Builder() - .setUuid(this.uuid) - .setComponentUuid(this.componentUuid) - .setPackageUrl(this.packageUrl) - .setPackageManager(this.packageManager) - .setPackageName(this.packageName) - .setVersion(this.version) - .setLicenseExpression(this.licenseExpression) - .setDeclaredLicenseExpression(this.declaredLicenseExpression) - .setKnown(this.known) - .setNewInPullRequest(this.newInPullRequest) - .setCreatedAt(this.createdAt) - .setUpdatedAt(this.updatedAt); - } - - /** - * Returns an object whose .equals and .hashCode would match that of another ScaReleaseDto's - * identity() if the two ScaReleaseDto would count as duplicates within the sca_releases table - * (within a single analysis, so ignoring the componentUuid). - * This is different from the DTOs themselves being equal because some fields do not count in - * the identity of the row, and can be updated while preserving the identity. The method just - * returns Object and not a type, because it exists just to call .equals and .hashCode on. - * - * @return an object to be used for hashing and comparing ScaReleaseDto instances for identity - */ - public Identity identity() { - return new IdentityImpl(this); - } - - public interface Identity { - } - - private record IdentityImpl(String packageUrl) implements Identity { - IdentityImpl(ScaReleaseDto dto) { - this(dto.packageUrl()); - } - } - - public static class Builder { - private String uuid; - private String componentUuid; - private String packageUrl; - private PackageManager packageManager; - private String packageName; - private String version; - private String licenseExpression; - private String declaredLicenseExpression; - private boolean known; - private boolean newInPullRequest; - private long createdAt; - private long updatedAt; - - public Builder setUuid(String uuid) { - this.uuid = uuid; - return this; - } - - public Builder setComponentUuid(String componentUuid) { - this.componentUuid = componentUuid; - return this; - } - - public Builder setPackageUrl(String packageUrl) { - this.packageUrl = packageUrl; - return this; - } - - public Builder setPackageManager(PackageManager packageManager) { - this.packageManager = packageManager; - return this; - } - - public Builder setPackageName(String packageName) { - this.packageName = packageName; - return this; - } - - public Builder setVersion(String version) { - this.version = version; - return this; - } - - public Builder setLicenseExpression(String licenseExpression) { - this.licenseExpression = licenseExpression; - return this; - } - - public Builder setDeclaredLicenseExpression(String declaredLicenseExpression) { - this.declaredLicenseExpression = declaredLicenseExpression; - return this; - } - - public Builder setKnown(boolean known) { - this.known = known; - return this; - } - - public Builder setNewInPullRequest(boolean newInPullRequest) { - this.newInPullRequest = newInPullRequest; - return this; - } - - public Builder setCreatedAt(long createdAt) { - this.createdAt = createdAt; - return this; - } - - public Builder setUpdatedAt(long updatedAt) { - this.updatedAt = updatedAt; - return this; - } - - public ScaReleaseDto build() { - return new ScaReleaseDto( - uuid, componentUuid, packageUrl, packageManager, packageName, version, licenseExpression, declaredLicenseExpression, known, newInPullRequest, createdAt, updatedAt); - } - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesDao.java deleted file mode 100644 index 878276874de..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesDao.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import org.sonar.db.Dao; -import org.sonar.db.DbSession; -import org.sonar.db.Pagination; - -public class ScaReleasesDao implements Dao { - - private static ScaReleasesMapper mapper(DbSession session) { - return session.getMapper(ScaReleasesMapper.class); - } - - public void insert(DbSession session, ScaReleaseDto scaReleaseDto) { - mapper(session).insert(scaReleaseDto); - } - - public void deleteByUuid(DbSession session, String uuid) { - mapper(session).deleteByUuid(uuid); - } - - public Optional<ScaReleaseDto> selectByUuid(DbSession dbSession, String uuid) { - return Optional.ofNullable(mapper(dbSession).selectByUuid(uuid)); - } - - public List<ScaReleaseDto> selectByUuids(DbSession dbSession, Collection<String> uuids) { - return mapper(dbSession).selectByUuids(uuids); - } - - /** - * Retrieves all releases with a specific branch UUID, no other filtering is done by this method. - */ - public List<ScaReleaseDto> selectByBranchUuid(DbSession dbSession, String branchUuid) { - return mapper(dbSession).selectByBranchUuid(branchUuid); - } - - public List<ScaReleaseDto> selectByQuery(DbSession session, ScaReleasesQuery scaReleasesQuery, Pagination pagination) { - return mapper(session).selectByQuery(scaReleasesQuery, pagination); - } - - public int countByQuery(DbSession session, ScaReleasesQuery scaReleasesQuery) { - return mapper(session).countByQuery(scaReleasesQuery); - } - - public List<ScaReleaseByPackageManagerCountDto> countReleasesByPackageManager(DbSession session, ScaReleasesQuery scaReleasesQuery) { - return mapper(session).countReleasesByPackageManager(scaReleasesQuery); - } - - public void update(DbSession session, ScaReleaseDto scaReleaseDto) { - mapper(session).update(scaReleaseDto); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesDependenciesDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesDependenciesDao.java deleted file mode 100644 index b4b1d2c1564..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesDependenciesDao.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; -import org.sonar.db.Dao; -import org.sonar.db.DbSession; - -public class ScaReleasesDependenciesDao implements Dao { - - private static ScaReleasesMapper releasesMapper(DbSession session) { - return session.getMapper(ScaReleasesMapper.class); - } - - private static ScaDependenciesMapper dependenciesMapper(DbSession session) { - return session.getMapper(ScaDependenciesMapper.class); - } - - /** - * Obtain ScaReleaseDependenciesDto for each of the release uuids. - * - * @param dbSession db session - * @param uuids uuids for sca_releases - * @return the list of ScaReleaseDependenciesDto - */ - public List<ScaReleaseDependenciesDto> selectByReleaseUuids(DbSession dbSession, Collection<String> uuids) { - List<ScaReleaseDto> releases = releasesMapper(dbSession).selectByUuids(uuids); - return selectByReleaseDtos(dbSession, releases); - } - - /** - * Obtain ScaReleaseDependenciesDto wrapping each of the passed-in ScaReleaseDto and adding - * the dependencies list. - * - * @param dbSession db session - * @param releases ScaReleaseDto to be wrapped in ScaReleaseDependenciesDto after selecting dependencies - * @return the list of ScaReleaseDependenciesDto - */ - public List<ScaReleaseDependenciesDto> selectByReleaseDtos(DbSession dbSession, Collection<ScaReleaseDto> releases) { - // This has a somewhat abnormal implementation (not in the mapper xml) due to - // https://github.com/mybatis/mybatis-3/issues/101 , - // essentially a mapper cannot mix "creating immutable objects via constructor" (the <constructor> tag) - // "filling in child objects from another query" (the <collection> tag), because mybatis would have to - // be refactored to postpone creating the parent objects until it had loaded the child objects. - // Some options considered: - // 1. use mutable DTOs or temporary mutable DTOs that we then convert (lots of cruft) - // 2. use a single join query instead of two queries (result set duplicates the parent's columns for each child) - // 3. custom result handler doing something-or-other (not really worked out) - // 4. just don't use a mapper and have a Dao that delegates to other mappers (this solution) - List<ScaDependencyDto> dependencies = dependenciesMapper(dbSession).selectByReleaseUuids(releases.stream().map(ScaReleaseDto::uuid).toList()); - Map<String, List<ScaDependencyDto>> dependenciesGroupedByReleaseId = dependencies.stream().collect(Collectors.groupingBy(ScaDependencyDto::scaReleaseUuid)); - - return releases.stream().map(releaseDto -> { - // by returning empty list instead of omitting the release if there are no deps, we simulate a left join. - // We may never actually save dependency-less sca_releases in real life though, which means we may - // only be doing this so our tests don't always have to create dependencies in order to load releases - // through here. - var dependenciesDtos = Optional.ofNullable(dependenciesGroupedByReleaseId.get(releaseDto.uuid())).orElse(Collections.emptyList()); - return new ScaReleaseDependenciesDto(releaseDto, dependenciesDtos); - }).toList(); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesMapper.java deleted file mode 100644 index 0694271ee3f..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesMapper.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.Collection; -import java.util.List; -import org.apache.ibatis.annotations.Param; -import org.sonar.db.Pagination; - -public interface ScaReleasesMapper { - void insert(ScaReleaseDto dto); - - void deleteByUuid(String uuid); - - ScaReleaseDto selectByUuid(String uuid); - - List<ScaReleaseDto> selectByUuids(Collection<String> uuids); - - List<ScaReleaseDto> selectByBranchUuid(String branchUuid); - - List<ScaReleaseDto> selectByQuery(@Param("query") ScaReleasesQuery query, @Param("pagination") Pagination pagination); - - void update(ScaReleaseDto dto); - - int countByQuery(@Param("query") ScaReleasesQuery query); - - List<ScaReleaseByPackageManagerCountDto> countReleasesByPackageManager(@Param("query") ScaReleasesQuery query); -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesQuery.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesQuery.java deleted file mode 100644 index 1e24eaf8c6a..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaReleasesQuery.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import java.util.Locale; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; - -import static org.sonar.db.DaoUtils.buildLikeValue; -import static org.sonar.db.WildcardPosition.BEFORE_AND_AFTER; - -public record ScaReleasesQuery( - String branchUuid, - @Nullable Boolean direct, - @Nullable Boolean productionScope, - @Nullable List<String> packageManagers, - @Nullable Boolean newInPullRequest, - @Nullable String query) { - - /** - * Used by MyBatis mapper - */ - @CheckForNull - public String likeQuery() { - return query == null ? null : buildLikeValue(query.toLowerCase(Locale.ENGLISH), BEFORE_AND_AFTER); - } - - public Builder toBuilder() { - return new Builder() - .setBranchUuid(branchUuid) - .setDirect(direct) - .setProductionScope(productionScope) - .setPackageManagers(packageManagers) - .setNewInPullRequest(newInPullRequest) - .setQuery(query); - } - - public static class Builder { - private String branchUuid; - private Boolean direct; - private Boolean productionScope; - private List<String> packageManagers; - private Boolean newInPullRequest; - private String query; - - public Builder setBranchUuid(String branchUuid) { - this.branchUuid = branchUuid; - return this; - } - - public Builder setDirect(Boolean direct) { - this.direct = direct; - return this; - } - - public Builder setProductionScope(Boolean productionScope) { - this.productionScope = productionScope; - return this; - } - - public Builder setPackageManagers(List<String> packageManagers) { - this.packageManagers = packageManagers; - return this; - } - - public Builder setNewInPullRequest(Boolean newInPullRequest) { - this.newInPullRequest = newInPullRequest; - return this; - } - - public Builder setQuery(String query) { - this.query = query; - return this; - } - - public ScaReleasesQuery build() { - return new ScaReleasesQuery(branchUuid, direct, productionScope, packageManagers, newInPullRequest, query); - } - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaSeverity.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaSeverity.java deleted file mode 100644 index d7d0e63eafd..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaSeverity.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -/** - * The severity of a dependency issue found by SCA. - * This is calculated as a base severity (which may be based on a vulnerability's CVSS score - * or just based on the type of issue), and then analysis-specific factors such as reachability - * can be considered to get the final severity. - */ -public enum ScaSeverity { - INFO(5), - LOW(10), - MEDIUM(15), - HIGH(20), - BLOCKER(25); - - // this needs to match the DB varchar length - public static final int MAX_NAME_LENGTH = 15; - private final int databaseSortKey; - - ScaSeverity(int databaseSortKey) { - this.databaseSortKey = databaseSortKey; - } - - /** - * Returns the sort key for the severity in the database. - * We store the severity as a string for debuggability - * and so on, but to sort by severity we need an integer - * that gets higher as the severity gets more severe. - * The sort keys have gaps so we could add new - * in-between values to the enum without a big data migration. - * @return integer to sort by severity - */ - public final int databaseSortKey() { - return databaseSortKey; - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaVulnerabilityIssueDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaVulnerabilityIssueDto.java deleted file mode 100644 index 7746571d087..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaVulnerabilityIssueDto.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.math.BigDecimal; -import java.util.List; -import javax.annotation.Nullable; - -/** - * This table has GLOBAL rows spanning all analysis runs. It represents - * extra fields on all rows of sca_issues that are of {@link ScaIssueType#VULNERABILITY}, - * in other words it's a polymorphic child class of sca_issues. - * <p> - * The uuid primary key will match the primary key of the corresponding row in the sca_issues table. - * </p> - * <p> - * The base severity does not consider project-specific considerations such as reachability. - * </p> - * <p> - * At least in the current take, this table does not contain all attributes of a given - * vulnerability; it only contains those that we show in a list of issues, but not those - * that appear when we show full details of a vulnerability. The columns in this table - * need to be returned by the cloud endpoint that analyzes dependency files. - * </p> - */ -public record ScaVulnerabilityIssueDto( - String uuid, - ScaSeverity baseSeverity, - List<String> cweIds, - @Nullable BigDecimal cvssScore, - long createdAt, - long updatedAt) { - - // these need to match what's in the db - public static final int CWE_IDS_MAX_LENGTH = 255; - - public Builder toBuilder() { - return new Builder() - .setUuid(uuid) - .setBaseSeverity(baseSeverity) - .setCweIds(cweIds) - .setCvssScore(cvssScore) - .setCreatedAt(createdAt) - .setUpdatedAt(updatedAt); - } - - public static class Builder { - private String uuid; - private ScaSeverity baseSeverity; - private List<String> cweIds; - private BigDecimal cvssScore; - private long createdAt; - private long updatedAt; - - public Builder setUuid(String uuid) { - this.uuid = uuid; - return this; - } - - public Builder setBaseSeverity(ScaSeverity baseSeverity) { - this.baseSeverity = baseSeverity; - return this; - } - - public Builder setCweIds(List<String> cweIds) { - this.cweIds = cweIds; - return this; - } - - public Builder setCvssScore(BigDecimal cvssScore) { - this.cvssScore = cvssScore; - return this; - } - - public Builder setCreatedAt(long createdAt) { - this.createdAt = createdAt; - return this; - } - - public Builder setUpdatedAt(long updatedAt) { - this.updatedAt = updatedAt; - return this; - } - - public ScaVulnerabilityIssueDto build() { - return new ScaVulnerabilityIssueDto(uuid, baseSeverity, cweIds, cvssScore, createdAt, updatedAt); - } - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaVulnerabilityIssuesDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaVulnerabilityIssuesDao.java deleted file mode 100644 index d06bfb872da..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaVulnerabilityIssuesDao.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import org.sonar.db.Dao; -import org.sonar.db.DbSession; - -public class ScaVulnerabilityIssuesDao implements Dao { - - private static ScaVulnerabilityIssuesMapper mapper(DbSession session) { - return session.getMapper(ScaVulnerabilityIssuesMapper.class); - } - - public void insert(DbSession session, ScaVulnerabilityIssueDto scaVulnerabilityIssueDto) { - mapper(session).insert(scaVulnerabilityIssueDto); - } - - public Optional<ScaVulnerabilityIssueDto> selectByUuid(DbSession dbSession, String uuid) { - return Optional.ofNullable(mapper(dbSession).selectByUuid(uuid)); - } - - public List<ScaVulnerabilityIssueDto> selectByUuids(DbSession dbSession, Collection<String> uuids) { - return mapper(dbSession).selectByUuids(uuids); - } - - public void update(DbSession session, ScaVulnerabilityIssueDto scaVulnerabilityIssueDto) { - mapper(session).update(scaVulnerabilityIssueDto); - } -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaVulnerabilityIssuesMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaVulnerabilityIssuesMapper.java deleted file mode 100644 index 487039a1e06..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/ScaVulnerabilityIssuesMapper.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.Collection; -import java.util.List; - -public interface ScaVulnerabilityIssuesMapper { - void insert(ScaVulnerabilityIssueDto dto); - - ScaVulnerabilityIssueDto selectByUuid(String uuid); - - List<ScaVulnerabilityIssueDto> selectByUuids(Collection<String> uuids); - - void update(ScaVulnerabilityIssueDto dto); -} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/package-info.java b/server/sonar-db-dao/src/main/java/org/sonar/db/sca/package-info.java deleted file mode 100644 index 91273c3d426..00000000000 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/sca/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -@ParametersAreNonnullByDefault -package org.sonar.db.sca; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaDependenciesMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaDependenciesMapper.xml deleted file mode 100644 index c3aabf332f2..00000000000 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaDependenciesMapper.xml +++ /dev/null @@ -1,145 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> -<mapper namespace="org.sonar.db.sca.ScaDependenciesMapper"> - <!-- we're using a resultMap instead of the usual resultType approach in order to provide - a typeHandler for the chains column --> - <resultMap id="scaDependencyResultMap" type="org.sonar.db.sca.ScaDependencyDto"> - <constructor> - <idArg column="uuid" javaType="String"/> - <arg column="sca_release_uuid" javaType="String"/> - <!-- the underscore prefix means to use the primitive type instead of boxed type --> - <arg column="direct" javaType="_boolean"/> - <arg column="scope" javaType="String"/> - <arg column="production_scope" javaType="_boolean"/> - <arg column="user_dependency_file_path" javaType="String"/> - <arg column="lockfile_dependency_file_path" javaType="String"/> - <arg column="chains" typeHandler="org.sonar.db.sca.ListOfListOfStringsTypeHandler" jdbcType="CLOB" - javaType="java.util.List"/> - <arg column="new_in_pull_request" javaType="_boolean"/> - <arg column="created_at" javaType="_long"/> - <arg column="updated_at" javaType="_long"/> - </constructor> - </resultMap> - - <sql id="scaDependenciesColumns"> - sd.uuid, - sd.sca_release_uuid, - sd.direct, - sd.scope, - sd.production_scope, - sd.user_dependency_file_path, - sd.lockfile_dependency_file_path, - sd.chains, - sd.new_in_pull_request, - sd.created_at, - sd.updated_at - </sql> - - <insert id="insert" parameterType="org.sonar.db.sca.ScaDependencyDto" useGeneratedKeys="false"> - insert into sca_dependencies ( - uuid, - sca_release_uuid, - direct, - scope, - production_scope, - user_dependency_file_path, - lockfile_dependency_file_path, - chains, - new_in_pull_request, - created_at, - updated_at - ) values ( - #{uuid,jdbcType=VARCHAR}, - #{scaReleaseUuid,jdbcType=VARCHAR}, - #{direct,jdbcType=BOOLEAN}, - #{scope,jdbcType=VARCHAR}, - #{productionScope,jdbcType=BOOLEAN}, - #{userDependencyFilePath,jdbcType=VARCHAR}, - #{lockfileDependencyFilePath,jdbcType=VARCHAR}, - #{chains,jdbcType=CLOB,typeHandler=org.sonar.db.sca.ListOfListOfStringsTypeHandler}, - #{newInPullRequest,jdbcType=BOOLEAN}, - #{createdAt,jdbcType=BIGINT}, - #{updatedAt,jdbcType=BIGINT} - ) - </insert> - - <delete id="deleteByUuid" parameterType="string"> - delete from sca_dependencies - where uuid = #{uuid,jdbcType=VARCHAR} - </delete> - - <select id="selectByUuid" parameterType="string" resultMap="scaDependencyResultMap"> - select <include refid="scaDependenciesColumns"/> - from sca_dependencies sd - where sd.uuid = #{uuid,jdbcType=VARCHAR} - </select> - - <select id="selectByReleaseUuids" parameterType="string" resultMap="scaDependencyResultMap"> - select <include refid="scaDependenciesColumns"/> - from sca_dependencies sd - <if test="arg0.isEmpty()"> - where 1=0 - </if> - <if test="!arg0.isEmpty()"> - where sd.sca_release_uuid in - <foreach collection="collection" item="sca_release_uuid" open="(" close=")" separator=","> - #{sca_release_uuid, jdbcType=VARCHAR} - </foreach> - </if> - </select> - - <select id="selectByBranchUuid" parameterType="string" resultMap="scaDependencyResultMap"> - select <include refid="scaDependenciesColumns"/> - from sca_dependencies sd - inner join sca_releases sr on sd.sca_release_uuid = sr.uuid - where sr.component_uuid = #{branchUuid,jdbcType=VARCHAR} - </select> - - <select id="selectByQuery" parameterType="map" resultMap="scaDependencyResultMap"> - select <include refid="scaDependenciesColumns"/> - <include refid="sqlSelectByQuery"/> - ORDER BY sd.uuid ASC - <include refid="org.sonar.db.common.Common.pagination"/> - </select> - - <select id="countByQuery" resultType="int"> - select count(sd.uuid) - <include refid="sqlSelectByQuery"/> - </select> - - <sql id="sqlSelectByQuery"> - from sca_dependencies sd - inner join sca_releases sr on sd.sca_release_uuid = sr.uuid - where sr.component_uuid = #{query.branchUuid,jdbcType=VARCHAR} - <if test="query.direct != null"> - AND sd.direct = #{query.direct,jdbcType=BOOLEAN} - </if> - <if test="query.packageManagers != null and !query.packageManagers.isEmpty()"> - AND sr.package_manager IN - <foreach collection="query.packageManagers" open="(" close=")" item="packageManager" separator=","> - #{packageManager,jdbcType=VARCHAR} - </foreach> - </if> - <if test="query.query() != null"> - AND lower(sr.package_name) LIKE #{query.likeQuery} ESCAPE '/' - </if> - </sql> - - <update id="update" parameterType="org.sonar.db.sca.ScaDependencyDto" useGeneratedKeys="false"> - update sca_dependencies - set - uuid = #{uuid, jdbcType=VARCHAR}, - sca_release_uuid = #{scaReleaseUuid, jdbcType=VARCHAR}, - direct = #{direct, jdbcType=BOOLEAN}, - scope = #{scope, jdbcType=VARCHAR}, - production_scope = #{productionScope, jdbcType=BOOLEAN}, - user_dependency_file_path = #{userDependencyFilePath, jdbcType=VARCHAR}, - lockfile_dependency_file_path = #{lockfileDependencyFilePath, jdbcType=VARCHAR}, - chains = #{chains, jdbcType=CLOB, typeHandler=org.sonar.db.sca.ListOfListOfStringsTypeHandler}, - new_in_pull_request = #{newInPullRequest, jdbcType=BOOLEAN}, - updated_at = #{updatedAt, jdbcType=BIGINT} - where - uuid = #{uuid, jdbcType=VARCHAR} - </update> - -</mapper> diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesMapper.xml deleted file mode 100644 index 39e8b4eade8..00000000000 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesMapper.xml +++ /dev/null @@ -1,80 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> -<mapper namespace="org.sonar.db.sca.ScaIssuesMapper"> - <resultMap id="scaIssueResultMap" type="org.sonar.db.sca.ScaIssueDto"> - <constructor> - <idArg column="uuid" javaType="String"/> - <arg column="sca_issue_type" javaType="org.sonar.db.sca.ScaIssueType"/> - <arg column="package_url" javaType="String"/> - <arg column="vulnerability_id" javaType="String"/> - <arg column="spdx_license_id" javaType="String"/> - <arg column="created_at" javaType="_long"/> - <arg column="updated_at" javaType="_long"/> - </constructor> - </resultMap> - - <sql id="scaIssuesColumns"> - si.uuid, - si.sca_issue_type, - si.package_url, - si.vulnerability_id, - si.spdx_license_id, - si.created_at, - si.updated_at - </sql> - - <insert id="insert" parameterType="org.sonar.db.sca.ScaIssueDto" useGeneratedKeys="false"> - insert into sca_issues ( - uuid, - sca_issue_type, - package_url, - vulnerability_id, - spdx_license_id, - created_at, - updated_at - ) values ( - #{uuid,jdbcType=VARCHAR}, - #{scaIssueType,jdbcType=VARCHAR}, - #{packageUrl,jdbcType=VARCHAR}, - #{vulnerabilityId,jdbcType=VARCHAR}, - #{spdxLicenseId,jdbcType=VARCHAR}, - #{createdAt,jdbcType=BIGINT}, - #{updatedAt,jdbcType=BIGINT} - ) - </insert> - - <!-- delete is left out for now, because it is very dangerous without foreign key constraints and ON DELETE behavior, - and it hasn't yet been necessary to try to "garbage collect" this table. --> - - <select id="selectByUuid" parameterType="string" resultMap="scaIssueResultMap"> - select <include refid="scaIssuesColumns"/> - from sca_issues si - where si.uuid = #{uuid,jdbcType=VARCHAR} - </select> - - <select id="selectByUuids" parameterType="string" resultMap="scaIssueResultMap"> - select <include refid="scaIssuesColumns"/> - from sca_issues si - <if test="arg0.isEmpty()"> - where 1=0 - </if> - <if test="!arg0.isEmpty()"> - where si.uuid in - <foreach collection="collection" item="uuid" open="(" close=")" separator=","> - #{uuid, jdbcType=VARCHAR} - </foreach> - </if> - </select> - - <!-- selectByValue is used to upsert (get or create) the issues found in an analysis. --> - <select id="selectUuidByValue" parameterType="org.sonar.db.sca.ScaIssueIdentity" resultType="String"> - select si.uuid - from sca_issues si - where (si.sca_issue_type = #{scaIssueType,jdbcType=VARCHAR} - and si.package_url = #{packageUrl,jdbcType=VARCHAR} - and si.vulnerability_id = #{vulnerabilityId,jdbcType=VARCHAR} - and si.spdx_license_id = #{spdxLicenseId,jdbcType=VARCHAR}) - </select> - - <!-- there is no update operation; sca_issues table is append-only --> -</mapper> diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesDetailsMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesDetailsMapper.xml deleted file mode 100644 index fc5b3468983..00000000000 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesDetailsMapper.xml +++ /dev/null @@ -1,237 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> -<mapper namespace="org.sonar.db.sca.ScaIssuesReleasesDetailsMapper"> - <resultMap id="scaIssueReleaseDetailsResultMap" type="org.sonar.db.sca.ScaIssueReleaseDetailsDto"> - <constructor> - <idArg column="issue_release_uuid" javaType="String"/> - <arg resultMap="org.sonar.db.sca.ScaIssuesReleasesMapper.scaIssueReleaseResultMap" - columnPrefix="sir_" - javaType="org.sonar.db.sca.ScaIssueReleaseDto"/> - <arg resultMap="org.sonar.db.sca.ScaIssuesMapper.scaIssueResultMap" - columnPrefix="si_" - javaType="org.sonar.db.sca.ScaIssueDto"/> - <arg resultMap="org.sonar.db.sca.ScaReleasesMapper.scaReleaseResultMap" - columnPrefix="sr_" - javaType="org.sonar.db.sca.ScaReleaseDto"/> - <arg resultMap="org.sonar.db.sca.ScaVulnerabilityIssuesMapper.scaVulnerabilityIssueResultMap" - columnPrefix="svi_" - javaType="org.sonar.db.sca.ScaVulnerabilityIssueDto"/> - </constructor> - </resultMap> - - <sql id="columns"> - <!-- These have to match all of the properties in the other tables' mappers, - adding the columnPrefix given in our resultMap above --> - sir.uuid as issue_release_uuid, - sir.uuid as sir_uuid, - sir.sca_issue_uuid as sir_sca_issue_uuid, - sir.sca_release_uuid as sir_sca_release_uuid, - sir.severity as sir_severity, - sir.severity_sort_key as sir_severity_sort_key, - sir.created_at as sir_created_at, - sir.updated_at as sir_updated_at, - si.uuid as si_uuid, - si.sca_issue_type as si_sca_issue_type, - si.package_url as si_package_url, - si.vulnerability_id as si_vulnerability_id, - si.spdx_license_id as si_spdx_license_id, - si.created_at as si_created_at, - si.updated_at as si_updated_at, - sr.uuid as sr_uuid, - sr.component_uuid as sr_component_uuid, - sr.package_url as sr_package_url, - sr.package_manager as sr_package_manager, - sr.package_name as sr_package_name, - sr.version as sr_version, - sr.license_expression as sr_license_expression, - sr.declared_license_expression as sr_declared_license_expression, - sr.known as sr_known, - sr.new_in_pull_request as sr_new_in_pull_request, - sr.created_at as sr_created_at, - sr.updated_at as sr_updated_at, - svi.uuid as svi_uuid, - svi.base_severity as svi_base_severity, - svi.cwe_ids as svi_cwe_ids, - svi.cvss_score as svi_cvss_score, - svi.created_at as svi_created_at, - svi.updated_at as svi_updated_at - </sql> - - <sql id="columnsWithCvssSortKey"> - <include refid="columns"/>, - <!-- It seems that the behavior of NULL in ORDER BY varies by database backend, with different - defaults and a lack of universal support for NULLS FIRST / NULLS LAST. - This poses an issue for nullable columns we want to sort by such as cvss_score. - On databases that support it, NULLS FIRST could probably use the index while this COALESCE - hack does not, so maybe someday we want to conditionalize on db backend somehow. --> - <!-- NULL score is treated as least severe --> - COALESCE(svi.cvss_score, 0.0) as cvss_sort_key - </sql> - - <sql id="sqlBaseJoins"> - from sca_issues_releases sir - inner join sca_issues si on sir.sca_issue_uuid = si.uuid - inner join sca_releases sr on sir.sca_release_uuid = sr.uuid - left join sca_vulnerability_issues svi on sir.sca_issue_uuid = svi.uuid - </sql> - - <sql id="sqlSelectByScaIssueReleaseUuid"> - <include refid="sqlBaseJoins"/> - where sir.uuid = #{scaIssueReleaseUuid,jdbcType=VARCHAR} - </sql> - - <sql id="sqlSelectByReleaseUuid"> - <include refid="sqlBaseJoins"/> - where sr.uuid = #{releaseUuid,jdbcType=VARCHAR} - </sql> - - <sql id="sqlSelectByBranchUuid"> - <include refid="sqlBaseJoins"/> - where sr.component_uuid = #{branchUuid,jdbcType=VARCHAR} - </sql> - - <select id="selectByReleaseUuid" parameterType="map" resultMap="scaIssueReleaseDetailsResultMap"> - select <include refid="columnsWithCvssSortKey"/> - <include refid="sqlSelectByReleaseUuid"/> - <include refid="sqlOrderBySeverityDesc"/> - </select> - - <select id="selectByBranchUuid" parameterType="map" resultMap="scaIssueReleaseDetailsResultMap"> - select <include refid="columnsWithCvssSortKey"/> - <include refid="sqlSelectByBranchUuid"/> - <include refid="sqlOrderBySeverityDesc"/> - <include refid="org.sonar.db.common.Common.pagination"/> - </select> - - <select id="selectByScaIssueReleaseUuid" parameterType="map" resultMap="scaIssueReleaseDetailsResultMap"> - select <include refid="columns"/> - <include refid="sqlSelectByScaIssueReleaseUuid"/> - <!-- no ORDER BY here because it's always one result --> - </select> - - <select id="countByBranchUuid" parameterType="string" resultType="int"> - select count(sir.uuid) - <include refid="sqlSelectByBranchUuid"/> - </select> - - <sql id="sqlSelectByQueryWhereClause"> - <where> - sr.component_uuid = #{query.branchUuid,jdbcType=VARCHAR} - <if test="query.direct != null"> - <!-- we only want each sca_releases row once, so this isn't a join. Note that each release - can be BOTH direct and !direct if it has multiple dependencies. --> - AND exists (select 1 from sca_dependencies sd where sd.sca_release_uuid = sr.uuid and sd.direct = #{query.direct,jdbcType=BOOLEAN}) - </if> - <if test="query.productionScope != null"> - <!-- we only want each sca_releases row once, so this isn't a join. --> - AND exists (select 1 from sca_dependencies sd where sd.sca_release_uuid = sr.uuid and sd.production_scope = #{query.productionScope,jdbcType=BOOLEAN}) - </if> - <if test="query.vulnerabilityIdSubstring != null"> - <!-- this screens out non-vulnerability-having issue types even if the search is for empty string --> - AND si.vulnerability_id != '${@org.sonar.db.sca.ScaIssueDto@NULL_VALUE}' - <if test="query.vulnerabilityIdSubstring.length > 0"> - AND upper(si.vulnerability_id) LIKE #{query.vulnerabilityIdUppercaseEscapedAsLikeValue, jdbcType=VARCHAR} ESCAPE '/' - </if> - </if> - <if test="query.packageNameSubstring != null and query.packageNameSubstring.length > 0"> - AND lower(sr.package_name) LIKE #{query.packageNameLowercaseEscapedAsLikeValue, jdbcType=VARCHAR} ESCAPE '/' - </if> - <if test="query.newInPullRequest != null"> - AND sr.new_in_pull_request = #{query.newInPullRequest, jdbcType=BOOLEAN} - </if> - <if test="query.types != null"> - <if test="query.types.isEmpty()"> - AND 1=0 - </if> - <if test="!query.types.isEmpty()"> - AND si.sca_issue_type in - <foreach collection="query.types" open="(" close=")" item="type" separator=","> - #{type, jdbcType=VARCHAR} - </foreach> - </if> - </if> - <if test="query.severities != null"> - <if test="query.severities.isEmpty()"> - AND 1=0 - </if> - <if test="!query.severities.isEmpty()"> - AND sir.severity in - <foreach collection="query.severities" open="(" close=")" item="severity" separator=","> - #{severity, jdbcType=VARCHAR} - </foreach> - </if> - </if> - <if test="query.packageManagers != null"> - <if test="query.packageManagers.isEmpty()"> - AND 1=0 - </if> - <if test="!query.packageManagers.isEmpty()"> - AND sr.package_manager in - <foreach collection="query.packageManagers" open="(" close=")" item="packageManager" separator=","> - #{packageManager, jdbcType=VARCHAR} - </foreach> - </if> - </if> - </where> - </sql> - - <sql id="sqlIdentityOrderColumns"> - <!-- the unique index is ordered as: scaIssueType, vulnerabilityId, packageUrl, spdxLicenseId - so we're guessing (or hoping?) that is the most efficient sort order, and it should sort of make - more sense to users than random. This sort is alphabetical first by issue type then - by CVE ID or license name. --> - si.sca_issue_type ASC, si.vulnerability_id ASC, si.package_url ASC, si.spdx_license_id ASC, sir.uuid ASC - </sql> - - <!-- this is the default sort for the selects that don't have a sort parameter (i.e. not the query) - but is probably slower than the identity sort until/unless we create a matching index --> - <sql id="sqlOrderBySeverityDesc"> - ORDER BY sir.severity_sort_key DESC, cvss_sort_key DESC, <include refid="sqlIdentityOrderColumns"/> - </sql> - - <sql id="sqlOrderByQuery"> - <choose> - <when test="query.sort == @org.sonar.db.sca.ScaIssuesReleasesDetailsQuery$Sort@IDENTITY_ASC"> - ORDER BY <include refid="sqlIdentityOrderColumns"/> - </when> - <when test="query.sort == @org.sonar.db.sca.ScaIssuesReleasesDetailsQuery$Sort@IDENTITY_DESC"> - <!-- This is a bizarre and useless sort order and we really only have it for symmetry in the REST API --> - ORDER BY si.sca_issue_type DESC, si.vulnerability_id DESC, si.package_url DESC, si.spdx_license_id DESC, sir.uuid DESC - </when> - <when test="query.sort == @org.sonar.db.sca.ScaIssuesReleasesDetailsQuery$Sort@SEVERITY_ASC"> - <!-- because many severities are the same, we try to keep the user intent by ordering by cvss score secondarily --> - ORDER BY sir.severity_sort_key ASC, cvss_sort_key ASC, <include refid="sqlIdentityOrderColumns"/> - </when> - <when test="query.sort == @org.sonar.db.sca.ScaIssuesReleasesDetailsQuery$Sort@SEVERITY_DESC"> - <!-- because many severities are the same, we try to keep the user intent by ordering by cvss score secondarily --> - <include refid="sqlOrderBySeverityDesc"/> - </when> - <when test="query.sort == @org.sonar.db.sca.ScaIssuesReleasesDetailsQuery$Sort@CVSS_SCORE_ASC"> - <!-- because cvss score can be null, we try to keep the user intent by ordering by severity secondarily --> - ORDER BY cvss_sort_key ASC, sir.severity_sort_key ASC, <include refid="sqlIdentityOrderColumns"/> - </when> - <when test="query.sort == @org.sonar.db.sca.ScaIssuesReleasesDetailsQuery$Sort@CVSS_SCORE_DESC"> - <!-- because cvss score can be null, we try to keep the user intent by ordering by severity secondarily --> - ORDER BY cvss_sort_key DESC, sir.severity_sort_key DESC, <include refid="sqlIdentityOrderColumns"/> - </when> - <otherwise> - <!-- generate a noisy failure --> - ORDER BY SYNTAX ERROR SHOULD NOT BE REACHED - </otherwise> - </choose> - </sql> - - <select id="selectByQuery" parameterType="map" resultMap="scaIssueReleaseDetailsResultMap"> - select <include refid="columnsWithCvssSortKey"/> - <include refid="sqlBaseJoins"/> - <include refid="sqlSelectByQueryWhereClause"/> - <include refid="sqlOrderByQuery"/> - <include refid="org.sonar.db.common.Common.pagination"/> - </select> - - <select id="countByQuery" parameterType="string" resultType="int"> - select count(sir.uuid) - <include refid="sqlBaseJoins"/> - <include refid="sqlSelectByQueryWhereClause"/> - </select> -</mapper> diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesMapper.xml deleted file mode 100644 index 27895f8b276..00000000000 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaIssuesReleasesMapper.xml +++ /dev/null @@ -1,69 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> -<mapper namespace="org.sonar.db.sca.ScaIssuesReleasesMapper"> - <resultMap id="scaIssueReleaseResultMap" type="org.sonar.db.sca.ScaIssueReleaseDto"> - <constructor> - <idArg name="uuid" column="uuid" javaType="String"/> - <arg name="scaIssueUuid" column="sca_issue_uuid" javaType="String"/> - <arg name="scaReleaseUuid" column="sca_release_uuid" javaType="String"/> - <arg name="severity" column="severity" javaType="org.sonar.db.sca.ScaSeverity" jdbcType="VARCHAR"/> - <arg name="createdAt" column="created_at" javaType="_long"/> - <arg name="updatedAt" column="updated_at" javaType="_long"/> - </constructor> - </resultMap> - - <sql id="scaIssuesReleasesColumns"> - sir.uuid, - sir.sca_issue_uuid, - sir.sca_release_uuid, - sir.severity, - sir.created_at, - sir.updated_at - </sql> - - <insert id="insert" parameterType="org.sonar.db.sca.ScaIssueReleaseDto" useGeneratedKeys="false"> - insert into sca_issues_releases ( - uuid, - sca_issue_uuid, - sca_release_uuid, - severity, - severity_sort_key, - created_at, - updated_at - ) values ( - #{uuid,jdbcType=VARCHAR}, - #{scaIssueUuid,jdbcType=VARCHAR}, - #{scaReleaseUuid,jdbcType=VARCHAR}, - #{severity,jdbcType=VARCHAR}, - #{severitySortKey,jdbcType=INTEGER}, - #{createdAt,jdbcType=BIGINT}, - #{updatedAt,jdbcType=BIGINT} - ) - </insert> - - <delete id="deleteByUuid" parameterType="string"> - delete from sca_issues_releases - where uuid = #{uuid,jdbcType=VARCHAR} - </delete> - - <update id="update" parameterType="org.sonar.db.sca.ScaIssueReleaseDto" useGeneratedKeys="false"> - update sca_issues_releases - set - sca_issue_uuid = #{scaIssueUuid, jdbcType=VARCHAR}, - sca_release_uuid = #{scaReleaseUuid, jdbcType=VARCHAR}, - severity = #{severity, jdbcType=VARCHAR}, - severity_sort_key = #{severitySortKey, jdbcType=VARCHAR}, - updated_at = #{updatedAt, jdbcType=BIGINT} - where - uuid = #{uuid, jdbcType=VARCHAR} -</update> - - - <select id="selectByBranchUuid" parameterType="string" resultMap="scaIssueReleaseResultMap"> - select <include refid="scaIssuesReleasesColumns"/> - from sca_issues_releases sir - inner join sca_releases sr on sir.sca_release_uuid = sr.uuid - where sr.component_uuid = #{branchUuid,jdbcType=VARCHAR} - order by sir.uuid asc - </select> -</mapper> diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaReleasesMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaReleasesMapper.xml deleted file mode 100644 index b394011781f..00000000000 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaReleasesMapper.xml +++ /dev/null @@ -1,164 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> -<mapper namespace="org.sonar.db.sca.ScaReleasesMapper"> - <resultMap id="scaReleaseResultMap" type="org.sonar.db.sca.ScaReleaseDto"> - <constructor> - <idArg name="uuid" column="uuid" javaType="String"/> - <arg name="componentUuid" column="component_uuid" javaType="String"/> - <arg name="packageUrl" column="package_url" javaType="String"/> - <arg name="packageManager" column="package_manager" javaType="org.sonar.db.sca.PackageManager" jdbcType="VARCHAR"/> - <arg name="packageName" column="package_name" javaType="String"/> - <arg name="version" column="version" javaType="String"/> - <arg name="licenseExpression" column="license_expression" javaType="String"/> - <arg name="declaredLicenseExpression" column="declared_license_expression" javaType="String"/> - <arg name="known" column="known" javaType="_boolean"/> - <arg name="newInPullRequest" column="new_in_pull_request" javaType="_boolean"/> - <arg name="createdAt" column="created_at" javaType="_long"/> - <arg name="updatedAt" column="updated_at" javaType="_long"/> - </constructor> - </resultMap> - - <sql id="scaReleasesColumns"> - sr.uuid as uuid, - sr.component_uuid, - sr.package_url, - sr.package_manager, - sr.package_name, - sr.version, - sr.license_expression, - sr.declared_license_expression, - sr.known, - sr.new_in_pull_request, - sr.created_at, - sr.updated_at - </sql> - - <insert id="insert" parameterType="org.sonar.db.sca.ScaReleaseDto" useGeneratedKeys="false"> - insert into sca_releases ( - uuid, - component_uuid, - package_url, - package_manager, - package_name, - version, - license_expression, - declared_license_expression, - known, - new_in_pull_request, - created_at, - updated_at - ) values ( - #{uuid,jdbcType=VARCHAR}, - #{componentUuid,jdbcType=VARCHAR}, - #{packageUrl,jdbcType=VARCHAR}, - #{packageManager,jdbcType=VARCHAR}, - #{packageName,jdbcType=VARCHAR}, - #{version,jdbcType=VARCHAR}, - #{licenseExpression,jdbcType=VARCHAR}, - #{declaredLicenseExpression,jdbcType=VARCHAR}, - #{known,jdbcType=BOOLEAN}, - #{newInPullRequest,jdbcType=BOOLEAN}, - #{createdAt,jdbcType=BIGINT}, - #{updatedAt,jdbcType=BIGINT} - ) - </insert> - - <delete id="deleteByUuid" parameterType="string"> - delete from sca_releases - where uuid = #{uuid,jdbcType=VARCHAR} - </delete> - - <select id="selectByUuid" parameterType="string" resultMap="scaReleaseResultMap"> - select <include refid="scaReleasesColumns"/> - from sca_releases sr - where sr.uuid = #{uuid,jdbcType=VARCHAR} - </select> - - <select id="selectByUuids" parameterType="string" resultMap="scaReleaseResultMap"> - select <include refid="scaReleasesColumns"/> - from sca_releases sr - <if test="arg0.isEmpty()"> - where 1=0 - </if> - <if test="!arg0.isEmpty()"> - where sr.uuid in - <foreach collection="collection" item="uuid" open="(" close=")" separator=","> - #{uuid, jdbcType=VARCHAR} - </foreach> - </if> - </select> - - <sql id="scaReleasesOrderBy"> - sr.uuid ASC - </sql> - - <select id="selectByBranchUuid" parameterType="string" resultMap="scaReleaseResultMap"> - select <include refid="scaReleasesColumns"/> - from sca_releases sr - where sr.component_uuid = #{branchUuid,jdbcType=VARCHAR} - order by <include refid="scaReleasesOrderBy"/> - </select> - - <select id="selectByQuery" parameterType="map" resultMap="scaReleaseResultMap"> - select <include refid="scaReleasesColumns"/> - <include refid="sqlSelectByQuery"/> - ORDER BY <include refid="scaReleasesOrderBy"/> - <include refid="org.sonar.db.common.Common.pagination"/> - </select> - - <select id="countByQuery" resultType="int"> - select count(sr.uuid) - <include refid="sqlSelectByQuery"/> - </select> - - <select id="countReleasesByPackageManager" resultType="org.sonar.db.sca.ScaReleaseByPackageManagerCountDto"> - SELECT - package_manager AS packageManager, - count(sr.uuid) AS releaseCount - <include refid="sqlSelectByQuery"/> - GROUP BY package_manager - </select> - - <sql id="sqlSelectByQuery"> - from sca_releases sr - where sr.component_uuid = #{query.branchUuid,jdbcType=VARCHAR} - <if test="query.direct != null"> - <!-- we only want each sca_releases row once, so this isn't a join. --> - AND exists (select 1 from sca_dependencies sd where sd.sca_release_uuid = sr.uuid and sd.direct = #{query.direct,jdbcType=BOOLEAN}) - </if> - <if test="query.productionScope != null"> - <!-- we only want each sca_releases row once, so this isn't a join. --> - AND exists (select 1 from sca_dependencies sd where sd.sca_release_uuid = sr.uuid and sd.production_scope = #{query.productionScope,jdbcType=BOOLEAN}) - </if> - <if test="query.packageManagers != null and !query.packageManagers.isEmpty()"> - AND sr.package_manager IN - <foreach collection="query.packageManagers" open="(" close=")" item="packageManager" separator=","> - #{packageManager,jdbcType=VARCHAR} - </foreach> - </if> - <if test="query.newInPullRequest != null"> - AND sr.new_in_pull_request = #{query.newInPullRequest,jdbcType=BOOLEAN} - </if> - <if test="query.query() != null"> - AND lower(sr.package_name) LIKE #{query.likeQuery} ESCAPE '/' - </if> - </sql> - - <update id="update" parameterType="org.sonar.db.sca.ScaReleaseDto" useGeneratedKeys="false"> - update sca_releases - set - uuid = #{uuid, jdbcType=VARCHAR}, - component_uuid = #{componentUuid, jdbcType=VARCHAR}, - package_url = #{packageUrl, jdbcType=VARCHAR}, - package_manager = #{packageManager, jdbcType=VARCHAR}, - package_name = #{packageName, jdbcType=VARCHAR}, - version = #{version, jdbcType=VARCHAR}, - license_expression = #{licenseExpression, jdbcType=VARCHAR}, - declared_license_expression = #{declaredLicenseExpression, jdbcType=VARCHAR}, - known = #{known, jdbcType=BOOLEAN}, - new_in_pull_request = #{newInPullRequest, jdbcType=BOOLEAN}, - updated_at = #{updatedAt, jdbcType=BIGINT} - where - uuid = #{uuid, jdbcType=VARCHAR} - </update> -</mapper> diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaVulnerabilityIssuesMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaVulnerabilityIssuesMapper.xml deleted file mode 100644 index 1f9a7e07600..00000000000 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/sca/ScaVulnerabilityIssuesMapper.xml +++ /dev/null @@ -1,80 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" ?> -<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd"> -<mapper namespace="org.sonar.db.sca.ScaVulnerabilityIssuesMapper"> - <!-- we're using a resultMap instead of the usual resultType approach in order to provide - a typeHandler for the cwe_ids column --> - <resultMap id="scaVulnerabilityIssueResultMap" type="org.sonar.db.sca.ScaVulnerabilityIssueDto"> - <constructor> - <idArg column="uuid" javaType="String"/> - <arg column="base_severity" javaType="org.sonar.db.sca.ScaSeverity" jdbcType="VARCHAR"/> - <arg column="cwe_ids" typeHandler="org.sonar.db.sca.ListOfStringsTypeHandler" jdbcType="VARCHAR" - javaType="java.util.List"/> - <arg column="cvss_score" javaType="java.math.BigDecimal"/> - <!-- the underscore prefix means to use the primitive type instead of boxed type --> - <arg column="created_at" javaType="_long"/> - <arg column="updated_at" javaType="_long"/> - </constructor> - </resultMap> - - <sql id="scaVulnerabilityIssuesColumns"> - svi.uuid, - svi.base_severity, - svi.cwe_ids, - svi.cvss_score, - svi.created_at, - svi.updated_at - </sql> - - <insert id="insert" parameterType="org.sonar.db.sca.ScaVulnerabilityIssueDto" useGeneratedKeys="false"> - insert into sca_vulnerability_issues ( - uuid, - base_severity, - cwe_ids, - cvss_score, - created_at, - updated_at - ) values ( - #{uuid,jdbcType=VARCHAR}, - #{baseSeverity,jdbcType=VARCHAR}, - #{cweIds,jdbcType=VARCHAR,typeHandler=org.sonar.db.sca.ListOfStringsTypeHandler}, - #{cvssScore,jdbcType=DECIMAL}, - #{createdAt,jdbcType=BIGINT}, - #{updatedAt,jdbcType=BIGINT} - ) - </insert> - - <!-- delete is left out for now, because it is very dangerous without foreign key constraints and ON DELETE behavior, - and it hasn't yet been necessary to try to "garbage collect" this table. --> - - <select id="selectByUuid" parameterType="string" resultMap="scaVulnerabilityIssueResultMap"> - select <include refid="scaVulnerabilityIssuesColumns"/> - from sca_vulnerability_issues svi - where svi.uuid = #{uuid,jdbcType=VARCHAR} - </select> - - <select id="selectByUuids" parameterType="string" resultMap="scaVulnerabilityIssueResultMap"> - select <include refid="scaVulnerabilityIssuesColumns"/> - from sca_vulnerability_issues svi - <if test="arg0.isEmpty()"> - where 1=0 - </if> - <if test="!arg0.isEmpty()"> - where svi.uuid in - <foreach collection="collection" item="uuid" open="(" close=")" separator=","> - #{uuid, jdbcType=VARCHAR} - </foreach> - </if> - </select> - - <update id="update" parameterType="org.sonar.db.sca.ScaVulnerabilityIssueDto" useGeneratedKeys="false"> - update sca_vulnerability_issues - set - uuid = #{uuid, jdbcType=VARCHAR}, - base_severity = #{baseSeverity, jdbcType=VARCHAR}, - cwe_ids = #{cweIds, jdbcType=VARCHAR, typeHandler=org.sonar.db.sca.ListOfStringsTypeHandler}, - cvss_score = #{cvssScore, jdbcType=DECIMAL}, - updated_at = #{updatedAt, jdbcType=BIGINT} - where - uuid = #{uuid, jdbcType=VARCHAR} - </update> -</mapper> diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/DefaultScaIssueIdentityTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/DefaultScaIssueIdentityTest.java deleted file mode 100644 index 122e328a16b..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/DefaultScaIssueIdentityTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -class DefaultScaIssueIdentityTest { - - @Test - void test_constructWithValidValues() { - var issueIdentity = new DefaultScaIssueIdentity(ScaIssueType.VULNERABILITY, "packageUrl", "vulnerabilityId", "spdxLicenseId"); - assertEquals(ScaIssueType.VULNERABILITY, issueIdentity.scaIssueType()); - assertEquals("packageUrl", issueIdentity.packageUrl()); - assertEquals("vulnerabilityId", issueIdentity.vulnerabilityId()); - assertEquals("spdxLicenseId", issueIdentity.spdxLicenseId()); - } - - @Test - void test_throwsOnInvalidValues() { - assertThrows(IllegalArgumentException.class, () -> new DefaultScaIssueIdentity(ScaIssueType.VULNERABILITY, "", "vulnerabilityId", "spdxLicenseId")); - assertThrows(IllegalArgumentException.class, () -> new DefaultScaIssueIdentity(ScaIssueType.VULNERABILITY, null, "vulnerabilityId", "spdxLicenseId")); - assertThrows(IllegalArgumentException.class, () -> new DefaultScaIssueIdentity(ScaIssueType.VULNERABILITY, "packageUrl", "", "spdxLicenseId")); - assertThrows(IllegalArgumentException.class, () -> new DefaultScaIssueIdentity(ScaIssueType.VULNERABILITY, "packageUrl", null, "spdxLicenseId")); - assertThrows(IllegalArgumentException.class, () -> new DefaultScaIssueIdentity(ScaIssueType.VULNERABILITY, "packageUrl", "vulnerabilityId", "")); - assertThrows(IllegalArgumentException.class, () -> new DefaultScaIssueIdentity(ScaIssueType.VULNERABILITY, "packageUrl", "vulnerabilityId", null)); - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/PackageManagerTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/PackageManagerTest.java deleted file mode 100644 index eed4dcfa2aa..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/PackageManagerTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class PackageManagerTest { - - @Test - void test_namesAreShortEnough() { - for (PackageManager packageManager : PackageManager.values()) { - assertThat(packageManager.name().length()).isLessThanOrEqualTo(ScaReleaseDto.PACKAGE_MANAGER_MAX_LENGTH); - } - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaDependenciesQueryTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaDependenciesQueryTest.java deleted file mode 100644 index 7a88e9ba53a..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaDependenciesQueryTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; - -class ScaDependenciesQueryTest { - - @Test - void testLikeQuery() { - ScaDependenciesQuery scaDependenciesQuery = new ScaDependenciesQuery("branchUuid", null, null, "QUERY"); - assertEquals("query%", scaDependenciesQuery.likeQuery()); - } - - @Test - void testLikeQueryWithNullQuery() { - ScaDependenciesQuery scaDependenciesQuery = new ScaDependenciesQuery("branchUuid", null, null, null); - assertNull(scaDependenciesQuery.likeQuery()); - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaDependencyDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaDependencyDtoTest.java deleted file mode 100644 index 505a06d6f35..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaDependencyDtoTest.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import javax.annotation.Nullable; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -class ScaDependencyDtoTest { - - @Test - void test_toBuilder_build_shouldRoundTrip() { - var scaDependencyDto = new ScaDependencyDto("scaDependencyUuid", - "scaReleaseUuid", - true, - "compile", - false, - "some/path", - "another/path", - List.of(List.of("pkg:npm/fodo@1.0.0")), - true, - 1L, - 2L); - assertThat(scaDependencyDto.toBuilder().build()).isEqualTo(scaDependencyDto); - } - - @Test - void test_identity_shouldIgnoreUuidAndUpdatableFields() { - var scaDependencyDto = new ScaDependencyDto("scaDependencyUuid", - "scaReleaseUuid", - true, - "compile", - false, - "some/path", - "another/path", - List.of(List.of("pkg:npm/IGNORED@1.0.0")), - false, - 1L, - 2L); - var scaDependencyDtoDifferentButSameIdentity = new ScaDependencyDto("differentUuid", - "scaReleaseUuid", - true, - "compile", - true, - "some/path", - "another/path", - List.of(List.of("pkg:npm/DIFFERENT_ALSO_IGNORED@1.0.0")), - true, - 42L, - 57L); - assertThat(scaDependencyDto.identity()).isEqualTo(scaDependencyDtoDifferentButSameIdentity.identity()); - assertThat(scaDependencyDto).isNotEqualTo(scaDependencyDtoDifferentButSameIdentity); - } - - @Test - void test_identity_changingScaReleaseUuid() { - var scaDependencyDto = new ScaDependencyDto("scaDependencyUuid", - "scaReleaseUuid", - true, - "compile", - false, - "some/path", - "another/path", - List.of(List.of("pkg:npm/IGNORED@1.0.0")), - true, - 1L, - 2L); - var scaDependencyDtoChangedReleaseUuid = new ScaDependencyDto("scaDependencyUuid", - "scaReleaseUuidDifferent", - true, - "compile", - false, - "some/path", - "another/path", - List.of(List.of("pkg:npm/IGNORED@1.0.0")), - false, - 1L, - 2L); - assertThat(scaDependencyDto.identity()).isNotEqualTo(scaDependencyDtoChangedReleaseUuid.identity()); - assertThat(scaDependencyDto.identity().withScaReleaseUuid("scaReleaseUuidDifferent")).isEqualTo(scaDependencyDtoChangedReleaseUuid.identity()); - } - - @Test - void test_primaryDependencyFilePath() { - ScaDependencyDto withUserDependencyFilePath = newScaDependencyDto("manifest"); - assertThat(withUserDependencyFilePath.primaryDependencyFilePath()).isEqualTo("manifest"); - ScaDependencyDto withoutUserDependencyFilePath = newScaDependencyDto(null); - assertThat(withoutUserDependencyFilePath.primaryDependencyFilePath()).isEqualTo("lockfileDependencyFilePath"); - } - - private ScaDependencyDto newScaDependencyDto(@Nullable String userDependencyFilePath) { - return new ScaDependencyDto("dependencyUuid", - "scaReleaseUuid", - true, - "compile", - false, - userDependencyFilePath, - "lockfileDependencyFilePath", - List.of(List.of("pkg:npm/foo@1.0.0")), - false, - 1L, - 2L); - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaDependencyReleaseDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaDependencyReleaseDtoTest.java deleted file mode 100644 index a0be47c280f..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaDependencyReleaseDtoTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import javax.annotation.Nullable; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class ScaDependencyReleaseDtoTest { - - @Test - void test_primaryDependencyFilePath() { - ScaDependencyReleaseDto withUserDependencyFilePath = newScaDependencyReleaseDto("manifest"); - assertEquals("manifest", withUserDependencyFilePath.primaryDependencyFilePath()); - ScaDependencyReleaseDto withoutUserDependencyFilePath = newScaDependencyReleaseDto(null); - assertEquals("lockfileDependencyFilePath", withoutUserDependencyFilePath.primaryDependencyFilePath()); - } - - private ScaDependencyReleaseDto newScaDependencyReleaseDto(@Nullable String userDependencyFilePath) { - return new ScaDependencyReleaseDto("dependencyUuid", - "releaseUuid", - "componentUuid", - true, - "scope", - userDependencyFilePath, - "lockfileDependencyFilePath", - List.of(List.of("pkg:npm/foo@1.0.0")), - "packageUrl", - PackageManager.MAVEN, - "packageName", - "version", - "licenseExpression", - true); - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueDtoTest.java deleted file mode 100644 index da9eb91dddf..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueDtoTest.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import org.junit.jupiter.api.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -class ScaIssueDtoTest { - - @Test - void test_constructWithValidValues() { - var dto = new ScaIssueDto("uuid", ScaIssueType.VULNERABILITY, "packageUrl", "vulnerabilityId", "spdxLicenseId", 1L, 2L); - assertEquals("uuid", dto.uuid()); - assertEquals(ScaIssueType.VULNERABILITY, dto.scaIssueType()); - assertEquals("packageUrl", dto.packageUrl()); - assertEquals("vulnerabilityId", dto.vulnerabilityId()); - assertEquals("spdxLicenseId", dto.spdxLicenseId()); - assertEquals(1L, dto.createdAt()); - assertEquals(2L, dto.updatedAt()); - } - - @Test - void test_throwsOnInvalidValues() { - assertThrows(IllegalArgumentException.class, () -> new ScaIssueDto("uuid", ScaIssueType.VULNERABILITY, "", "vulnerabilityId", "spdxLicenseId", 1L, 2L)); - assertThrows(IllegalArgumentException.class, () -> new ScaIssueDto("uuid", ScaIssueType.VULNERABILITY, null, "vulnerabilityId", "spdxLicenseId", 1L, 2L)); - assertThrows(IllegalArgumentException.class, () -> new ScaIssueDto("uuid", ScaIssueType.VULNERABILITY, "packageUrl", "", "spdxLicenseId", 1L, 2L)); - assertThrows(IllegalArgumentException.class, () -> new ScaIssueDto("uuid", ScaIssueType.VULNERABILITY, "packageUrl", null, "spdxLicenseId", 1L, 2L)); - assertThrows(IllegalArgumentException.class, () -> new ScaIssueDto("uuid", ScaIssueType.VULNERABILITY, "packageUrl", "vulnerabilityId", "", 1L, 2L)); - assertThrows(IllegalArgumentException.class, () -> new ScaIssueDto("uuid", ScaIssueType.VULNERABILITY, "packageUrl", "vulnerabilityId", null, 1L, 2L)); - } - - @Test - void test_constructFromIdentity() { - var identity = new DefaultScaIssueIdentity(ScaIssueType.VULNERABILITY, "packageUrl", "vulnerabilityId", "spdxLicenseId"); - var dto = new ScaIssueDto("uuid", identity, 1L, 2L); - assertEquals("uuid", dto.uuid()); - assertEquals(ScaIssueType.VULNERABILITY, dto.scaIssueType()); - assertEquals("packageUrl", dto.packageUrl()); - assertEquals("vulnerabilityId", dto.vulnerabilityId()); - assertEquals("spdxLicenseId", dto.spdxLicenseId()); - assertEquals(1L, dto.createdAt()); - assertEquals(2L, dto.updatedAt()); - } - - @Test - void test_toBuilder_build_shouldRoundTrip() { - var dto = new ScaIssueDto("uuid", ScaIssueType.VULNERABILITY, "packageUrl", "vulnerabilityId", "spdxLicenseId", 1L, 2L); - assertEquals(dto.toBuilder().build(), dto); - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueReleaseDetailsDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueReleaseDetailsDtoTest.java deleted file mode 100644 index a5e62a7d417..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueReleaseDetailsDtoTest.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.math.BigDecimal; -import java.util.List; -import org.assertj.core.api.ThrowableAssert; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; - -class ScaIssueReleaseDetailsDtoTest { - private static ScaIssueDto newSampleIssueDto() { - return new ScaIssueDto("issueUuid", - ScaIssueType.VULNERABILITY, - "packageUrl", - "vulnerabilityId", - "spdxLicenseId", - 1L, - 2L); - } - - private static ScaReleaseDto newSampleReleaseDto() { - return new ScaReleaseDto("releaseUuid", - "componentUuid", - "packageUrl", - PackageManager.MAVEN, - "foo:bar", - "1.0.0", - "MIT", - "NOASSERTION", - true, - false, - 2L, - 3L); - } - - private static ScaIssueReleaseDto newSampleIssueReleaseDto(ScaIssueDto issueDto, ScaReleaseDto releaseDto) { - return new ScaIssueReleaseDto( - "issueReleaseUuid", - issueDto.uuid(), - releaseDto.uuid(), - ScaSeverity.INFO, - 3L, - 4L); - } - - private static ScaVulnerabilityIssueDto newSampleVulnerabilityIssueDto(ScaIssueDto issueDto) { - return new ScaVulnerabilityIssueDto( - issueDto.uuid(), - ScaSeverity.HIGH, - List.of("cwe1"), - BigDecimal.ONE, - 5L, - 6L); - } - - private static ScaIssueReleaseDetailsDto newSampleIssueReleaseDetailsDto() { - var issueDto = newSampleIssueDto(); - var releaseDto = newSampleReleaseDto(); - var issueReleaseDto = newSampleIssueReleaseDto(issueDto, releaseDto); - var vulnerabilityIssueDto = newSampleVulnerabilityIssueDto(issueDto); - return new ScaIssueReleaseDetailsDto( - issueReleaseDto.uuid(), - issueReleaseDto, - issueDto, - releaseDto, - vulnerabilityIssueDto); - } - - @Test - void test_toBuilder_build_shouldRoundTrip() { - var dto = newSampleIssueReleaseDetailsDto(); - assertThat(dto.toBuilder().build()).isEqualTo(dto); - } - - @Test - void test_withMismatchedReleaseInIssueReleaseDto_throwsIllegalArgumentException() { - var validDto = newSampleIssueReleaseDetailsDto(); - var differentIssueReleaseDto = validDto.issueReleaseDto().toBuilder().setScaReleaseUuid("differentUuid").build(); - var invalidBuilder = validDto.toBuilder().setIssueReleaseDto(differentIssueReleaseDto); - assertThatThrownBy(invalidBuilder::build).isInstanceOf(IllegalArgumentException.class); - } - - @Test - void test_withMismatchedIssueInIssueReleaseDto_throwsIllegalArgumentException() { - var validDto = newSampleIssueReleaseDetailsDto(); - var differentIssueReleaseDto = validDto.issueReleaseDto().toBuilder().setScaIssueUuid("differentUuid").build(); - var invalidBuilder = validDto.toBuilder().setIssueReleaseDto(differentIssueReleaseDto); - assertThatThrownBy(invalidBuilder::build).isInstanceOf(IllegalArgumentException.class); - } - - @Test - void test_withMismatchedIssueReleaseUuid_throwsIllegalArgumentException() { - var validDto = newSampleIssueReleaseDetailsDto(); - ThrowableAssert.ThrowingCallable constructInvalid = () -> new ScaIssueReleaseDetailsDto("differentUuid", - validDto.issueReleaseDto(), validDto.issueDto(), validDto.releaseDto(), validDto.vulnerabilityIssueDto()); - assertThatThrownBy(constructInvalid).isInstanceOf(IllegalArgumentException.class); - } - - @Test - void test_withMismatchedVulnerabilityIssue_throwsIllegalArgumentException() { - var validDto = newSampleIssueReleaseDetailsDto(); - var differentVulnerabiiltyIssue = validDto.vulnerabilityIssueDto().toBuilder().setUuid("differentUuid").build(); - var invalidBuilder = validDto.toBuilder().setVulnerabilityIssueDto(differentVulnerabiiltyIssue); - assertThatThrownBy(invalidBuilder::build).isInstanceOf(IllegalArgumentException.class); - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueReleaseDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueReleaseDtoTest.java deleted file mode 100644 index e1df2cfd1c2..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueReleaseDtoTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -class ScaIssueReleaseDtoTest { - - @Test - void test_toBuilder_build_shouldRoundTrip() { - var scaIssueReleaseDto = new ScaIssueReleaseDto("sca-issue-release-uuid", - "sca-issue-uuid", - "sca-release-uuid", - ScaSeverity.INFO, - 1L, - 2L); - assertThat(scaIssueReleaseDto.toBuilder().build()).isEqualTo(scaIssueReleaseDto); - } - - @Test - void test_identity_shouldIgnoreUuidAndUpdatableFields() { - var scaIssueReleaseDto = new ScaIssueReleaseDto("sca-issue-release-uuid", - "sca-issue-uuid", - "sca-release-uuid", - ScaSeverity.INFO, - 1L, - 2L); - var scaIssueReleaseDtoDifferentButSameIdentity = new ScaIssueReleaseDto("differentUuid", - "sca-issue-uuid", - "sca-release-uuid", - ScaSeverity.HIGH, - 10L, - 20L); - assertThat(scaIssueReleaseDto.identity()).isEqualTo(scaIssueReleaseDtoDifferentButSameIdentity.identity()); - assertThat(scaIssueReleaseDto).isNotEqualTo(scaIssueReleaseDtoDifferentButSameIdentity); - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueTypeTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueTypeTest.java deleted file mode 100644 index 3027f5e96bd..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssueTypeTest.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class ScaIssueTypeTest { - - @Test - void test_namesAreShortEnough() { - for (ScaIssueType issueType : ScaIssueType.values()) { - assertThat(issueType.name().length()).isLessThanOrEqualTo(ScaIssueDto.SCA_ISSUE_TYPE_MAX_LENGTH); - } - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssuesReleasesDetailsQueryTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssuesReleasesDetailsQueryTest.java deleted file mode 100644 index e295fc6b3b4..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaIssuesReleasesDetailsQueryTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import org.assertj.core.api.AssertionsForClassTypes; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class ScaIssuesReleasesDetailsQueryTest { - - @Test - void test_toBuilder_build_shouldRoundTrip() { - var query = new ScaIssuesReleasesDetailsQuery("branchUuid", ScaIssuesReleasesDetailsQuery.Sort.IDENTITY_ASC, - true, true, "vulnerabilityIdSubstring", "packageNameSubstring", true, - List.of(ScaIssueType.VULNERABILITY), List.of(ScaSeverity.BLOCKER), List.of(PackageManager.NPM)); - AssertionsForClassTypes.assertThat(query.toBuilder().build()).isEqualTo(query); - } - - @Test - void test_queryParameterValues() { - for (var value : ScaIssuesReleasesDetailsQuery.Sort.values()) { - var queryParameterValue = value.queryParameterValue(); - var fromQueryParameterValue = ScaIssuesReleasesDetailsQuery.Sort.fromQueryParameterValue(queryParameterValue); - assertThat(fromQueryParameterValue).contains(value); - assertThat((queryParameterValue.startsWith("+") && value.name().endsWith("_ASC")) || - (queryParameterValue.startsWith("-") && value.name().endsWith("_DESC"))) - .as("+/- prefix and ASC/DESC suffix line up") - .isTrue(); - } - } - - @Test - void test_whenValueIsInvalid_fromQueryParameterValue() { - assertThat(ScaIssuesReleasesDetailsQuery.Sort.fromQueryParameterValue("invalid")).isEmpty(); - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaReleaseDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaReleaseDtoTest.java deleted file mode 100644 index 6c0ac3d9e53..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaReleaseDtoTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; - -class ScaReleaseDtoTest { - - @Test - void test_toBuilder_build_shouldRoundTrip() { - var scaReleaseDto = new ScaReleaseDto("scaReleaseUuid", - "componentUuid", - "packageUrl", - PackageManager.MAVEN, - "foo:bar", - "1.0.0", - "MIT", - "MIT", - true, - false, - 1L, - 2L); - assertThat(scaReleaseDto.toBuilder().build()).isEqualTo(scaReleaseDto); - } - - @Test - void test_identity_shouldIgnoreUuidAndUpdatableFields() { - var scaReleaseDto = new ScaReleaseDto("scaReleaseUuid", - "componentUuid", - "packageUrl", - PackageManager.MAVEN, - "foo:bar", - "1.0.0", - "MIT", - "MIT", - true, - false, - 1L, - 2L); - var scaReleaseDtoDifferentButSameIdentity = new ScaReleaseDto("differentUuid", - "componentUuidDifferent", - "packageUrl", - PackageManager.NPM, - "foo:bar-different", - "2.0.0", - "GPL-3.0", - "GPL-3.0", - false, - true, - 10L, - 30L); - assertThat(scaReleaseDto.identity()).isEqualTo(scaReleaseDtoDifferentButSameIdentity.identity()); - assertThat(scaReleaseDto).isNotEqualTo(scaReleaseDtoDifferentButSameIdentity); - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaReleasesQueryTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaReleasesQueryTest.java deleted file mode 100644 index 23a16876ac9..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaReleasesQueryTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import org.assertj.core.api.AssertionsForClassTypes; -import org.junit.jupiter.api.Test; - -class ScaReleasesQueryTest { - @Test - void test_toBuilder_build_shouldRoundTrip() { - var query = new ScaReleasesQuery("branchUuid", - true, false, List.of("NPM"), true, "query"); - AssertionsForClassTypes.assertThat(query.toBuilder().build()).isEqualTo(query); - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaSeverityTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaSeverityTest.java deleted file mode 100644 index 023f2bd9b20..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaSeverityTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.stream.Stream; -import org.junit.jupiter.api.Test; -import org.sonar.api.issue.impact.Severity; - -import static org.assertj.core.api.Assertions.assertThat; - -class ScaSeverityTest { - private static void assertSortOrder(ScaSeverity lower, ScaSeverity higher) { - assertThat(lower.databaseSortKey()) - .as(lower + " sorts below " + higher) - .isLessThan(higher.databaseSortKey()); - } - - @Test - void test_maxLength() { - for (ScaSeverity severity : ScaSeverity.values()) { - assertThat(severity.name().length()).as(severity.name() + " is short enough") - .isLessThanOrEqualTo(ScaSeverity.MAX_NAME_LENGTH); - } - } - - @Test - void test_sortKeysInOrder() { - assertSortOrder(ScaSeverity.INFO, ScaSeverity.LOW); - assertSortOrder(ScaSeverity.LOW, ScaSeverity.MEDIUM); - assertSortOrder(ScaSeverity.MEDIUM, ScaSeverity.HIGH); - assertSortOrder(ScaSeverity.HIGH, ScaSeverity.BLOCKER); - } - - @Test - void test_matchesImpactSeverity() { - assertThat(Stream.of(ScaSeverity.values()).map(Enum::name).toList()) - .as("ScaSeverity has the same values in the same order as impact.Severity") - .isEqualTo(Stream.of(Severity.values()).map(Enum::name).toList()); - } -} diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaVulnerabilityIssueDtoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaVulnerabilityIssueDtoTest.java deleted file mode 100644 index 1019f1e3e5d..00000000000 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/sca/ScaVulnerabilityIssueDtoTest.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.math.BigDecimal; -import java.util.List; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class ScaVulnerabilityIssueDtoTest { - @Test - void test_cweIdsLength_handledByTypeHandler() { - // this test is here to prevent accidentally messing it up - assertThat(ScaVulnerabilityIssueDto.CWE_IDS_MAX_LENGTH).isLessThanOrEqualTo(ListOfStringsTypeHandler.MAXIMUM_LENGTH); - } - - @Test - void test_toBuilder_build_shouldRoundTrip() { - var scaVulnerabilityIssueDto = new ScaVulnerabilityIssueDto("sca-issue-uuid", - ScaSeverity.INFO, - List.of("cwe"), - new BigDecimal("7.1"), - 1L, - 2L); - assertThat(scaVulnerabilityIssueDto.toBuilder().build()).isEqualTo(scaVulnerabilityIssueDto); - } -} diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java index 41975647b49..866b89dfadb 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/DbTester.java @@ -56,11 +56,6 @@ import org.sonar.db.property.PropertyDbTester; import org.sonar.db.qualitygate.QualityGateDbTester; import org.sonar.db.qualityprofile.QualityProfileDbTester; import org.sonar.db.rule.RuleDbTester; -import org.sonar.db.sca.ScaDependenciesDbTester; -import org.sonar.db.sca.ScaIssuesDbTester; -import org.sonar.db.sca.ScaIssuesReleasesDbTester; -import org.sonar.db.sca.ScaIssuesReleasesDetailsDbTester; -import org.sonar.db.sca.ScaReleasesDbTester; import org.sonar.db.source.FileSourceTester; import org.sonar.db.user.UserDbTester; import org.sonar.db.webhook.WebhookDbTester; @@ -101,11 +96,6 @@ public class DbTester extends AbstractDbTester<TestDbImpl> implements BeforeEach private final AlmPatsDbTester almPatsDbtester; private final AuditDbTester auditDbTester; private final AnticipatedTransitionDbTester anticipatedTransitionDbTester; - private final ScaDependenciesDbTester scaDependenciesDbTester; - private final ScaIssuesDbTester scaIssuesDbTester; - private final ScaIssuesReleasesDbTester scaIssuesReleasesDbTester; - private final ScaIssuesReleasesDetailsDbTester scaIssuesReleasesDetailsDbTester; - private final ScaReleasesDbTester scaReleasesDbTester; private DbTester(UuidFactory uuidFactory, System2 system2, @Nullable String schemaPath, AuditPersister auditPersister, MyBatisConfExtension... confExtensions) { super(TestDbImpl.create(schemaPath, confExtensions)); @@ -138,11 +128,6 @@ public class DbTester extends AbstractDbTester<TestDbImpl> implements BeforeEach this.almPatsDbtester = new AlmPatsDbTester(this); this.auditDbTester = new AuditDbTester(this); this.anticipatedTransitionDbTester = new AnticipatedTransitionDbTester(this); - this.scaDependenciesDbTester = new ScaDependenciesDbTester(this); - this.scaIssuesDbTester = new ScaIssuesDbTester(this); - this.scaIssuesReleasesDbTester = new ScaIssuesReleasesDbTester(this); - this.scaIssuesReleasesDetailsDbTester = new ScaIssuesReleasesDetailsDbTester(this); - this.scaReleasesDbTester = new ScaReleasesDbTester(this); } public static DbTester create() { @@ -294,22 +279,6 @@ public class DbTester extends AbstractDbTester<TestDbImpl> implements BeforeEach return anticipatedTransitionDbTester; } - public ScaDependenciesDbTester getScaDependenciesDbTester() { - return scaDependenciesDbTester; - } - - public ScaIssuesDbTester getScaIssuesDbTester() { - return scaIssuesDbTester; - } - - public ScaIssuesReleasesDetailsDbTester getScaIssuesReleasesDetailsDbTester() { - return scaIssuesReleasesDetailsDbTester; - } - - public ScaReleasesDbTester getScaReleasesDbTester() { - return scaReleasesDbTester; - } - @Override public void afterEach(ExtensionContext context) throws Exception { after(); diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaDependenciesDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaDependenciesDbTester.java deleted file mode 100644 index 97d6a718ea5..00000000000 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaDependenciesDbTester.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.List; -import java.util.function.Function; -import javax.annotation.Nullable; -import org.sonar.db.DbClient; -import org.sonar.db.DbTester; -import org.sonar.db.component.ComponentDto; - -public class ScaDependenciesDbTester { - private final DbTester db; - private final DbClient dbClient; - - public ScaDependenciesDbTester(DbTester db) { - this.db = db; - this.dbClient = db.getDbClient(); - } - - public static ScaDependencyDto newScaDependencyDto(String scaReleaseUuid, String suffix) { - return newScaDependencyDto(scaReleaseUuid, suffix, null); - } - - public static ScaDependencyDto newScaDependencyDto(String scaReleaseUuid, String suffix, boolean direct) { - return newScaDependencyDto(scaReleaseUuid, suffix, builder -> builder.setDirect(direct)); - } - - public static ScaDependencyDto newScaDependencyDto(String scaReleaseUuid, String suffix, @Nullable Function<ScaDependencyDto.Builder, ScaDependencyDto.Builder> customizer) { - long now = 1348L; - var builder = new ScaDependencyDto("scaDependencyUuid" + suffix, - scaReleaseUuid, - true, - "compile", - false, - "pom.xml", - "package-lock.json", - List.of(List.of("pkg:npm/foo@1.0.0")), - false, - now, - now).toBuilder(); - if (customizer != null) { - builder = customizer.apply(builder); - } - return builder.build(); - } - - public ComponentDto newComponentDto(String branchUuid, String suffix) { - return new ComponentDto().setUuid("uuid" + suffix) - .setKey("key" + suffix) - .setUuidPath("uuidPath" + suffix) - .setBranchUuid(branchUuid); - } - - public ComponentDto insertComponent(String branchUuid, String suffix) { - ComponentDto componentDto = newComponentDto(branchUuid, suffix); - db.components().insertComponent(componentDto); - return componentDto; - } - - public ScaDependencyDto insertScaDependency(String scaReleaseUuid, String suffix, Function<ScaDependencyDto.Builder, ScaDependencyDto.Builder> customizer) { - ScaDependencyDto scaDependencyDto = newScaDependencyDto(scaReleaseUuid, suffix, customizer); - dbClient.scaDependenciesDao().insert(db.getSession(), scaDependencyDto); - return scaDependencyDto; - } - - public ScaDependencyDto insertScaDependency(ScaReleaseDto scaReleaseDto, String suffix, Function<ScaDependencyDto.Builder, ScaDependencyDto.Builder> customizer) { - return insertScaDependency(scaReleaseDto.uuid(), suffix, customizer); - } - - public ScaDependencyDto insertScaDependency(String scaReleaseUuid, String suffix) { - ScaDependencyDto scaDependencyDto = newScaDependencyDto(scaReleaseUuid, suffix); - dbClient.scaDependenciesDao().insert(db.getSession(), scaDependencyDto); - return scaDependencyDto; - } - - public ScaDependencyDto insertScaDependency(ScaReleaseDto scaReleaseDto, String suffix) { - return insertScaDependency(scaReleaseDto.uuid(), suffix); - } - - public ScaDependencyDto insertScaDependency(String scaReleaseUuid, String suffix, boolean direct) { - ScaDependencyDto scaDependencyDto = newScaDependencyDto(scaReleaseUuid, suffix, direct); - dbClient.scaDependenciesDao().insert(db.getSession(), scaDependencyDto); - return scaDependencyDto; - } - - public ScaDependencyDto insertScaDependency(ScaReleaseDto scaReleaseDto, String suffix, boolean direct) { - return insertScaDependency(scaReleaseDto.uuid(), suffix, direct); - } - - public ScaDependencyDto insertScaDependencyWithRelease(String componentUuid, String suffix, boolean direct, PackageManager packageManager, String packageName) { - var scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentUuid, suffix, packageManager, packageName); - return insertScaDependency(scaReleaseDto.uuid(), suffix, direct); - } - - public ScaDependencyDto insertScaDependencyWithRelease(String componentUuid, String suffix, Function<ScaDependencyDto.Builder, ScaDependencyDto.Builder> customizer, - PackageManager packageManager, String packageName) { - var scaReleaseDto = db.getScaReleasesDbTester().insertScaRelease(componentUuid, suffix, packageManager, packageName); - return insertScaDependency(scaReleaseDto.uuid(), suffix, customizer); - } -} diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaIssuesDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaIssuesDbTester.java deleted file mode 100644 index c7c26bbd0ae..00000000000 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaIssuesDbTester.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.math.BigDecimal; -import java.util.List; -import java.util.Map; -import org.sonar.db.DbClient; -import org.sonar.db.DbTester; - -public class ScaIssuesDbTester { - private static final Map<String, String> SAMPLE_LICENSES_BY_SUFFIX = Map.of( - "1", "MIT", - "2", "0BSD", - "3", "GPL-3.0", - "4", "Apache-2.0", - "5", "BSD-3-Clause"); - - private final DbTester db; - private final DbClient dbClient; - - public ScaIssuesDbTester(DbTester db) { - this.db = db; - this.dbClient = db.getDbClient(); - } - - public static ScaVulnerabilityIssueDto newVulnerabilityIssueDto(String suffix) { - return new ScaVulnerabilityIssueDto("sca-issue-uuid" + suffix, ScaSeverity.INFO, List.of("cwe" + suffix), new BigDecimal("7.1"), 1L, 2L); - } - - public static ScaIssueDto newVulnerabilityScaIssueDto(String suffix) { - return new ScaIssueDto("sca-issue-uuid" + suffix, ScaIssueType.VULNERABILITY, "fakePackageUrl" + suffix, "fakeVulnerabilityId" + suffix, ScaIssueDto.NULL_VALUE, 1L, - 2L); - } - - public static ScaIssueDto newProhibitedLicenseScaIssueDto(String suffix) { - return new ScaIssueDto("sca-issue-uuid" + suffix, ScaIssueType.PROHIBITED_LICENSE, ScaIssueDto.NULL_VALUE, ScaIssueDto.NULL_VALUE, - SAMPLE_LICENSES_BY_SUFFIX.getOrDefault(suffix, "GPL-3.0-only"), 1L, 2L); - } - - Map.Entry<ScaIssueDto, ScaVulnerabilityIssueDto> newVulnerabilityIssue(String suffix) { - var scaIssueDto = newVulnerabilityScaIssueDto(suffix); - var vulnerabilityIssueDto = newVulnerabilityIssueDto(suffix); - return Map.entry(scaIssueDto, vulnerabilityIssueDto); - } - - Map.Entry<ScaIssueDto, ScaVulnerabilityIssueDto> insertVulnerabilityIssue(String suffix) { - var scaIssueDto = newVulnerabilityScaIssueDto(suffix); - var vulnerabilityIssueDto = newVulnerabilityIssueDto(suffix); - - dbClient.scaIssuesDao().insert(db.getSession(), scaIssueDto); - dbClient.scaVulnerabilityIssuesDao().insert(db.getSession(), vulnerabilityIssueDto); - return Map.entry(scaIssueDto, vulnerabilityIssueDto); - } - - ScaIssueDto insertProhibitedLicenseIssue(String suffix) { - var scaIssueDto = newProhibitedLicenseScaIssueDto(suffix); - dbClient.scaIssuesDao().insert(db.getSession(), scaIssueDto); - return scaIssueDto; - } -} diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaIssuesReleasesDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaIssuesReleasesDbTester.java deleted file mode 100644 index 7e1b39fd260..00000000000 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaIssuesReleasesDbTester.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import org.sonar.db.DbClient; -import org.sonar.db.DbTester; - -public class ScaIssuesReleasesDbTester { - private final DbTester db; - private final DbClient dbClient; - - public ScaIssuesReleasesDbTester(DbTester db) { - this.db = db; - this.dbClient = db.getDbClient(); - } - - public static ScaIssueReleaseDto fromDtos(ScaIssueDto issueDto, ScaReleaseDto releaseDto, String suffix) { - return new ScaIssueReleaseDto("issueReleaseUuid" + suffix, issueDto.uuid(), releaseDto.uuid(), ScaSeverity.INFO, 89L, 90L); - } - - public static IssueReleaseData newProhibitedLicenseIssueReleaseDto(String suffix) { - var issueDto = ScaIssuesDbTester.newProhibitedLicenseScaIssueDto(suffix); - var releaseDto = ScaReleasesDbTester.newScaReleaseDto(suffix); - var issueReleaseDto = fromDtos(issueDto, releaseDto, suffix); - return new IssueReleaseData(issueReleaseDto, issueDto, releaseDto, null); - } - - public static IssueReleaseData newVulnerabilityIssueReleaseDto(String suffix) { - var issueDto = ScaIssuesDbTester.newVulnerabilityScaIssueDto(suffix); - var vulnerabiiltyIssueDto = ScaIssuesDbTester.newVulnerabilityIssueDto(suffix); - var releaseDto = ScaReleasesDbTester.newScaReleaseDto(suffix); - var issueReleaseDto = fromDtos(issueDto, releaseDto, suffix); - return new IssueReleaseData(issueReleaseDto, issueDto, releaseDto, vulnerabiiltyIssueDto); - } - - public IssueReleaseData insertProhibitedLicenseIssueReleaseDto(String suffix) { - var data = newProhibitedLicenseIssueReleaseDto(suffix); - dbClient.scaIssuesDao().insert(db.getSession(), data.issueDto); - dbClient.scaReleasesDao().insert(db.getSession(), data.releaseDto); - dbClient.scaIssuesReleasesDao().insert(db.getSession(), data.issueReleaseDto); - return data; - } - - public IssueReleaseData insertVulnerabilityIssueReleaseDto(String suffix) { - var data = newVulnerabilityIssueReleaseDto(suffix); - dbClient.scaIssuesDao().insert(db.getSession(), data.issueDto); - dbClient.scaReleasesDao().insert(db.getSession(), data.releaseDto); - dbClient.scaIssuesReleasesDao().insert(db.getSession(), data.issueReleaseDto); - dbClient.scaVulnerabilityIssuesDao().insert(db.getSession(), data.vulnerabilityIssueDto); - return data; - } - - public record IssueReleaseData( - ScaIssueReleaseDto issueReleaseDto, - ScaIssueDto issueDto, - ScaReleaseDto releaseDto, - ScaVulnerabilityIssueDto vulnerabilityIssueDto) { - } -} diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaIssuesReleasesDetailsDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaIssuesReleasesDetailsDbTester.java deleted file mode 100644 index 869a62e61a2..00000000000 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaIssuesReleasesDetailsDbTester.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import java.util.Optional; -import java.util.function.Function; -import javax.annotation.Nullable; -import org.sonar.db.DbClient; -import org.sonar.db.DbTester; - -import static org.assertj.core.api.Assertions.assertThat; - -public class ScaIssuesReleasesDetailsDbTester { - private final DbTester db; - private final DbClient dbClient; - - public ScaIssuesReleasesDetailsDbTester(DbTester db) { - this.db = db; - this.dbClient = db.getDbClient(); - } - - public static ScaIssueReleaseDetailsDto fromIssueReleaseData(ScaIssuesReleasesDbTester.IssueReleaseData issueReleaseData) { - return new ScaIssueReleaseDetailsDto( - issueReleaseData.issueReleaseDto().uuid(), - issueReleaseData.issueReleaseDto(), - issueReleaseData.issueDto(), - issueReleaseData.releaseDto(), - issueReleaseData.vulnerabilityIssueDto()); - } - - public static ScaIssueReleaseDetailsDto fromDtos(ScaIssueReleaseDto issueReleaseDto, ScaIssueDto issueDto, - Optional<ScaVulnerabilityIssueDto> vulnerabilityIssueDtoOptional, ScaReleaseDto releaseDto) { - return new ScaIssueReleaseDetailsDto(issueReleaseDto.uuid(), issueReleaseDto, - issueDto, releaseDto, vulnerabilityIssueDtoOptional.orElse(null)); - } - - private ScaIssueReleaseDetailsDto insertIssue(ScaIssueDto scaIssue, Optional<ScaVulnerabilityIssueDto> scaVulnerabilityIssueDtoOptional, - String suffix, String componentUuid) { - // insertScaRelease has suffix and componentUuid swapped vs. our own method... - var scaRelease = db.getScaReleasesDbTester().insertScaRelease(componentUuid, suffix); - var scaIssueRelease = new ScaIssueReleaseDto("sca-issue-release-uuid-" + suffix, scaIssue, scaRelease, ScaSeverity.INFO, 1L, 2L); - dbClient.scaIssuesReleasesDao().insert(db.getSession(), scaIssueRelease); - return fromDtos(scaIssueRelease, scaIssue, scaVulnerabilityIssueDtoOptional, scaRelease); - } - - public ScaIssueReleaseDetailsDto insertVulnerabilityIssue(String suffix, String componentUuid) { - var entry = db.getScaIssuesDbTester().insertVulnerabilityIssue(suffix); - return insertIssue(entry.getKey(), Optional.of(entry.getValue()), suffix, componentUuid); - } - - public ScaIssueReleaseDetailsDto insertProhibitedLicenseIssue(String suffix, String componentUuid) { - var scaIssue = db.getScaIssuesDbTester().insertProhibitedLicenseIssue(suffix); - return insertIssue(scaIssue, Optional.empty(), suffix, componentUuid); - } - - public ScaIssueReleaseDetailsDto insertIssue(ScaIssueType scaIssueType, String suffix, String componentUuid) { - return insertIssue(scaIssueType, suffix, componentUuid, - null, null, null, null); - } - - public ScaIssueReleaseDetailsDto insertIssue(ScaIssueType scaIssueType, String suffix, String componentUuid, - @Nullable Function<ScaIssueDto, ScaIssueDto> scaIssueModifier, - @Nullable Function<ScaVulnerabilityIssueDto, ScaVulnerabilityIssueDto> scaVulnerabilityIssueModifier, - @Nullable Function<ScaReleaseDto, ScaReleaseDto> scaReleaseModifier, - @Nullable Function<ScaIssueReleaseDto, ScaIssueReleaseDto> scaIssueReleaseModifier) { - var scaRelease = ScaReleasesDbTester.newScaReleaseDto(componentUuid, suffix, PackageManager.MAVEN, "packageName" + suffix); - if (scaReleaseModifier != null) { - scaRelease = scaReleaseModifier.apply(scaRelease); - } - // little hack here because it's useful to allow providing a release that already exists - var existing = dbClient.scaReleasesDao().selectByUuid(db.getSession(), scaRelease.uuid()); - if (existing.isEmpty()) { - dbClient.scaReleasesDao().insert(db.getSession(), scaRelease); - } else { - assertThat(existing).contains(scaRelease); - } - var scaIssue = switch (scaIssueType) { - case PROHIBITED_LICENSE -> ScaIssuesDbTester.newProhibitedLicenseScaIssueDto(suffix); - case VULNERABILITY -> ScaIssuesDbTester.newVulnerabilityScaIssueDto(suffix); - }; - if (scaIssueModifier != null) { - scaIssue = scaIssueModifier.apply(scaIssue); - } - dbClient.scaIssuesDao().insert(db.getSession(), scaIssue); - ScaVulnerabilityIssueDto scaVulnerabilityIssue = null; - if (scaIssue.scaIssueType() == ScaIssueType.VULNERABILITY) { - scaVulnerabilityIssue = ScaIssuesDbTester.newVulnerabilityIssueDto(suffix); - if (!scaVulnerabilityIssue.uuid().equals(scaIssue.uuid())) { - throw new IllegalStateException("ScaVulnerabilityIssueDto.uuid must match ScaIssueDto.uuid or we won't find the ScaVueberabilityIssueDto"); - } - if (scaVulnerabilityIssueModifier != null) { - scaVulnerabilityIssue = scaVulnerabilityIssueModifier.apply(scaVulnerabilityIssue); - } - dbClient.scaVulnerabilityIssuesDao().insert(db.getSession(), scaVulnerabilityIssue); - } - var scaIssueRelease = new ScaIssueReleaseDto("sca-issue-release-uuid-" + suffix, scaIssue, scaRelease, ScaSeverity.INFO, 1L, 2L); - if (scaIssueReleaseModifier != null) { - scaIssueRelease = scaIssueReleaseModifier.apply(scaIssueRelease); - } - dbClient.scaIssuesReleasesDao().insert(db.getSession(), scaIssueRelease); - return fromDtos(scaIssueRelease, scaIssue, Optional.ofNullable(scaVulnerabilityIssue), scaRelease); - } -} diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaReleasesDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaReleasesDbTester.java deleted file mode 100644 index 0921c265bfa..00000000000 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/sca/ScaReleasesDbTester.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2025 SonarSource SA - * mailto:info AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.db.sca; - -import org.sonar.db.DbClient; -import org.sonar.db.DbTester; - -public class ScaReleasesDbTester { - private final DbTester db; - private final DbClient dbClient; - - public ScaReleasesDbTester(DbTester db) { - this.db = db; - this.dbClient = db.getDbClient(); - } - - public static ScaReleaseDto newScaReleaseDto(String suffix) { - return newScaReleaseDto("componentUuid_release_" + suffix, suffix, PackageManager.MAVEN, "packageName" + suffix); - } - - public static ScaReleaseDto newScaReleaseDto(String componentUuid, String suffix, PackageManager packageManager, String packageName) { - return new ScaReleaseDto("scaReleaseUuid" + suffix, - componentUuid, - "packageUrl" + suffix, - packageManager, - packageName, - "1.0.0-" + suffix, - "MIT", - "MIT", - true, - false, - 1L, - 2L); - } - - public ScaReleaseDto insertScaRelease(String componentUuid, String suffix) { - return insertScaRelease(componentUuid, suffix, PackageManager.MAVEN, "packageName" + suffix); - } - - public ScaReleaseDto insertScaRelease(String componentUuid, String suffix, PackageManager packageManager, String packageName) { - var scaReleaseDto = newScaReleaseDto(componentUuid, suffix, packageManager, packageName); - dbClient.scaReleasesDao().insert(db.getSession(), scaReleaseDto); - return scaReleaseDto; - } - - /** - * Inserts a release and also dependencyCount sca_dependencies that depend on that release. - */ - public ScaReleaseDto insertScaReleaseWithDependency(String componentUuid, String suffix, int dependencyCount, boolean direct, PackageManager packageManager, String packageName) { - var scaReleaseDto = insertScaRelease(componentUuid, suffix, packageManager, packageName); - while (dependencyCount > 0) { - db.getScaDependenciesDbTester().insertScaDependency(scaReleaseDto, suffix + "-" + dependencyCount, direct); - dependencyCount--; - } - return scaReleaseDto; - } -} |