diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2022-04-28 16:22:34 -0500 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-05-25 20:03:15 +0000 |
commit | c28353ec8b036b74bb070ca03420bfea29b1ca8d (patch) | |
tree | 497cfdff35c4a4bea3713b9c4001b28105ab8834 /server | |
parent | 251e1fa5c7bb38ce93dc426ae2e395d44819f721 (diff) | |
download | sonarqube-c28353ec8b036b74bb070ca03420bfea29b1ca8d.tar.gz sonarqube-c28353ec8b036b74bb070ca03420bfea29b1ca8d.zip |
SONAR-16316 DAO to fetch report issues from DB
SONAR-16316 Export CSV files with issues
SONAR-16316 Create Web API 'api/regulatory_reports/download'
SONAR-16316 Export Scanner Context
SONAR-16316 Write report zip file
SONAR-16316 Integrate pdf report in zip file
Diffstat (limited to 'server')
13 files changed, 345 insertions, 11 deletions
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 c0c487f2f34..01893f01de6 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 @@ -75,6 +75,7 @@ import org.sonar.db.qualityprofile.QProfileEditGroupsDao; import org.sonar.db.qualityprofile.QProfileEditUsersDao; import org.sonar.db.qualityprofile.QualityProfileDao; import org.sonar.db.qualityprofile.QualityProfileExportDao; +import org.sonar.db.report.RegulatoryReportDao; import org.sonar.db.rule.RuleDao; import org.sonar.db.rule.RuleRepositoryDao; import org.sonar.db.scannercache.ScannerAnalysisCacheDao; @@ -152,6 +153,7 @@ public class DaoModule extends Module { QualityGateUserPermissionsDao.class, QualityProfileDao.class, QualityProfileExportDao.class, + RegulatoryReportDao.class, RoleDao.class, RuleDao.class, RuleRepositoryDao.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 d545de23ae5..b883f7623d2 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 @@ -75,6 +75,7 @@ import org.sonar.db.qualityprofile.QProfileEditGroupsDao; import org.sonar.db.qualityprofile.QProfileEditUsersDao; import org.sonar.db.qualityprofile.QualityProfileDao; import org.sonar.db.qualityprofile.QualityProfileExportDao; +import org.sonar.db.report.RegulatoryReportDao; import org.sonar.db.rule.RuleDao; import org.sonar.db.rule.RuleRepositoryDao; import org.sonar.db.scannercache.ScannerAnalysisCacheDao; @@ -122,6 +123,7 @@ public class DbClient { private final PermissionTemplateDao permissionTemplateDao; private final PermissionTemplateCharacteristicDao permissionTemplateCharacteristicDao; private final IssueDao issueDao; + private final RegulatoryReportDao regulatoryReportDao; private final IssueChangeDao issueChangeDao; private final CeActivityDao ceActivityDao; private final CeQueueDao ceQueueDao; @@ -219,6 +221,7 @@ public class DbClient { qualityGateGroupPermissionsDao = getDao(map, QualityGateGroupPermissionsDao.class); projectQgateAssociationDao = getDao(map, ProjectQgateAssociationDao.class); duplicationDao = getDao(map, DuplicationDao.class); + regulatoryReportDao = getDao(map, RegulatoryReportDao.class); notificationQueueDao = getDao(map, NotificationQueueDao.class); metricDao = getDao(map, MetricDao.class); groupDao = getDao(map, GroupDao.class); @@ -290,6 +293,10 @@ public class DbClient { return issueDao; } + public RegulatoryReportDao regulatoryReportDao() { + return regulatoryReportDao; + } + public IssueChangeDao issueChangeDao() { return issueChangeDao; } 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 462ea745804..112752428a3 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 @@ -131,6 +131,7 @@ import org.sonar.db.qualityprofile.QProfileEditGroupsMapper; import org.sonar.db.qualityprofile.QProfileEditUsersMapper; import org.sonar.db.qualityprofile.QualityProfileExportMapper; import org.sonar.db.qualityprofile.QualityProfileMapper; +import org.sonar.db.report.RegulatoryReportMapper; import org.sonar.db.rule.RuleMapper; import org.sonar.db.rule.RuleParamDto; import org.sonar.db.rule.RuleRepositoryMapper; @@ -292,6 +293,7 @@ public class MyBatis { QualityGateUserPermissionsMapper.class, QualityProfileMapper.class, QualityProfileExportMapper.class, + RegulatoryReportMapper.class, RoleMapper.class, RuleMapper.class, RuleRepositoryMapper.class, diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/newcodeperiod/NewCodePeriodDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/newcodeperiod/NewCodePeriodDao.java index c59df0ef221..82b2d02702b 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/newcodeperiod/NewCodePeriodDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/newcodeperiod/NewCodePeriodDao.java @@ -90,6 +90,13 @@ public class NewCodePeriodDao implements Dao { return ofNullable(mapper(dbSession).selectByBranch(projectUuid, branchUuid)); } + public NewCodePeriodDto selectBestMatchForBranch(DbSession dbSession, String projectUuid, String branchUuid) { + return selectByBranch(dbSession, projectUuid, branchUuid) + .or(() -> selectByProject(dbSession, projectUuid) + .or(() -> selectGlobal(dbSession))) + .orElse(NewCodePeriodDto.defaultInstance()); + } + public Set<String> selectBranchesReferencing(DbSession dbSession, String projectUuid, String referenceBranchName) { return mapper(dbSession).selectBranchesReferencing(projectUuid, referenceBranchName); } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/report/IssueFindingDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/report/IssueFindingDto.java new file mode 100644 index 00000000000..b1fdfe9f761 --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/report/IssueFindingDto.java @@ -0,0 +1,108 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 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.report; + +import java.util.Set; +import javax.annotation.CheckForNull; +import org.sonar.api.rules.RuleType; +import org.sonar.db.rule.RuleDto; + +public class IssueFindingDto { + private String kee; + private String message; + private int type; + private String severity; + private boolean isManualSeverity; + private String ruleKey; + private String ruleRepository; + private String ruleName; + private String status; + private String resolution; + private String fileName; + private Integer line; + private String securityStandards; + private boolean isNewCodeReferenceIssue; + private long creationDate; + + public String getStatus() { + return status; + } + + @CheckForNull + public String getRuleName() { + return ruleName; + } + + public String getKey() { + return kee; + } + + public Set<String> getSecurityStandards() { + return RuleDto.deserializeSecurityStandardsString(securityStandards); + } + + public boolean isManualSeverity() { + return isManualSeverity; + } + + @CheckForNull + public String getResolution() { + return resolution; + } + + @CheckForNull + public String getMessage() { + return message; + } + + public RuleType getType() { + return RuleType.valueOf(type); + } + + public String getSeverity() { + return severity; + } + + public String getRuleKey() { + return ruleKey; + } + + public String getRuleRepository() { + return ruleRepository; + } + + @CheckForNull + public String getFileName() { + return fileName; + } + + @CheckForNull + public Integer getLine() { + return line; + } + + public boolean isNewCodeReferenceIssue() { + return isNewCodeReferenceIssue; + } + + public long getCreationDate() { + return creationDate; + } +} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/report/RegulatoryReportDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/report/RegulatoryReportDao.java new file mode 100644 index 00000000000..8cd4a7c350b --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/report/RegulatoryReportDao.java @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 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.report; + +import org.apache.ibatis.session.ResultHandler; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; + +public class RegulatoryReportDao implements Dao { + public void scrollIssues(DbSession dbSession, String branchUuid, ResultHandler<IssueFindingDto> handler) { + mapper(dbSession).scrollIssues(branchUuid, handler); + } + + private static RegulatoryReportMapper mapper(DbSession dbSession) { + return dbSession.getMapper(RegulatoryReportMapper.class); + } + +} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/report/RegulatoryReportMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/report/RegulatoryReportMapper.java new file mode 100644 index 00000000000..1a75e22bdcb --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/report/RegulatoryReportMapper.java @@ -0,0 +1,26 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 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.report; + +import org.apache.ibatis.session.ResultHandler; + +public interface RegulatoryReportMapper { + void scrollIssues(String branchUuid, ResultHandler<IssueFindingDto> handler); +} diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/report/package-info.java b/server/sonar-db-dao/src/main/java/org/sonar/db/report/package-info.java new file mode 100644 index 00000000000..35263a2e558 --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/report/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 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.report; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/report/RegulatoryReportMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/report/RegulatoryReportMapper.xml new file mode 100644 index 00000000000..84787bdc8ca --- /dev/null +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/report/RegulatoryReportMapper.xml @@ -0,0 +1,36 @@ +<?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.report.RegulatoryReportMapper"> + <sql id="issueColumns"> + i.kee as kee, + i.severity as severity, + i.manual_severity as isManualSeverity, + i.message as message, + i.line as line, + i.status as status, + i.resolution as resolution, + p.kee as componentKey, + p.path as fileName, + i.issue_type as type, + r.plugin_name as ruleRepository, + r.plugin_rule_key as ruleKey, + r.security_standards as securityStandards, + r.name as ruleName, + i.issue_creation_date as creationDate, + <include refid="org.sonar.db.issue.IssueMapper.isNewCodeReferenceIssue"/> + </sql> + + <select id="scrollIssues" parameterType="String" resultType="org.sonar.db.report.IssueFindingDto" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY"> + select + <include refid="issueColumns"/> + from issues i + inner join rules r on r.uuid=i.rule_uuid + inner join components p on p.uuid=i.component_uuid + left join new_code_reference_issues n on i.kee = n.issue_key + where i.project_uuid=#{branchUuid,jdbcType=VARCHAR} + and i.status !='CLOSED' + </select> + +</mapper> diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/report/RegulatoryReportDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/report/RegulatoryReportDaoTest.java new file mode 100644 index 00000000000..81411f30ae4 --- /dev/null +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/report/RegulatoryReportDaoTest.java @@ -0,0 +1,87 @@ +/* + * SonarQube + * Copyright (C) 2009-2022 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.report; + +import java.util.ArrayList; +import java.util.List; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.utils.System2; +import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.issue.IssueDto; +import org.sonar.db.rule.RuleDto; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX; +import static org.sonar.db.component.ComponentTesting.newFileDto; + +public class RegulatoryReportDaoTest { + private static final String PROJECT_UUID = "prj_uuid"; + private static final String PROJECT_KEY = "prj_key"; + private static final String FILE_UUID = "file_uuid"; + private static final String FILE_KEY = "file_key"; + + @Rule + public DbTester db = DbTester.create(System2.INSTANCE); + + private final RegulatoryReportDao underTest = db.getDbClient().regulatoryReportDao(); + private ComponentDto project; + private RuleDto rule; + private ComponentDto file; + + @Before + public void prepare() { + rule = db.rules().insertRule(); + project = db.components().insertPrivateProject(t -> t.setProjectUuid(PROJECT_UUID).setUuid(PROJECT_UUID).setDbKey(PROJECT_KEY)); + file = db.components().insertComponent(newFileDto(project).setUuid(FILE_UUID).setDbKey(FILE_KEY)); + } + + @Test + public void scrollIssues_returns_all_non_closed_issues_for_project() { + IssueDto issue1 = db.issues().insertIssue(rule, project, file, i -> i.setStatus("OPEN").setResolution(null)); + IssueDto issue2 = db.issues().insertIssue(rule, project, file, i -> i.setStatus("CONFIRMED").setResolution(null)); + IssueDto issue3 = db.issues().insertIssue(rule, project, file, i -> i.setStatus("RESOLVED").setResolution(RESOLUTION_WONT_FIX)); + + // not returned + IssueDto issue4 = db.issues().insertIssue(rule, project, file, i -> i.setStatus("CLOSED").setResolution(null)); + ComponentDto otherProject = db.components().insertPrivateProject(); + ComponentDto otherFile = db.components().insertComponent(newFileDto(otherProject)); + IssueDto issue5 = db.issues().insertIssue(rule, otherProject, otherFile); + + List<IssueFindingDto> issues = new ArrayList<>(); + underTest.scrollIssues(db.getSession(), PROJECT_UUID, result -> issues.add(result.getResultObject())); + assertThat(issues).extracting(IssueFindingDto::getKey).containsOnly(issue1.getKey(), issue2.getKey(), issue3.getKey()); + + // check fields + IssueFindingDto issue = issues.stream().filter(i -> i.getKey().equals(issue1.getKey())).findFirst().get(); + assertThat(issue.getFileName()).isEqualTo(file.path()); + assertThat(issue.getRuleName()).isEqualTo(rule.getName()); + assertThat(issue.getRuleKey()).isEqualTo(rule.getRuleKey()); + assertThat(issue.getRuleRepository()).isEqualTo(rule.getRepositoryKey()); + assertThat(issue.getMessage()).isEqualTo(issue1.getMessage()); + assertThat(issue.getLine()).isEqualTo(issue1.getLine()); + assertThat(issue.getSeverity()).isEqualTo(issue1.getSeverity()); + assertThat(issue.getType().getDbConstant()).isEqualTo(issue1.getType()); + assertThat(issue.getSecurityStandards()).isEqualTo(rule.getSecurityStandards()); + assertThat(issue.isManualSeverity()).isEqualTo(issue1.isManualSeverity()); + } +} diff --git a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/issue/IssueDbTester.java b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/issue/IssueDbTester.java index 595183d387d..e57b9166489 100644 --- a/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/issue/IssueDbTester.java +++ b/server/sonar-db-dao/src/testFixtures/java/org/sonar/db/issue/IssueDbTester.java @@ -226,4 +226,9 @@ public class IssueDbTester { db.commit(); } + public void insertNewCodeReferenceIssue(IssueDto issue) { + db.getDbClient().issueDao().insertAsNewCodeOnReferenceBranch(db.getSession(), IssueTesting.newCodeReferenceIssue(issue)); + db.commit(); + } + } diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginJarLoader.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginJarLoader.java index 0f2eb7ccab9..a39998be132 100644 --- a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginJarLoader.java +++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginJarLoader.java @@ -34,6 +34,7 @@ import java.util.Map; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; +import javax.inject.Inject; import org.apache.commons.io.FileUtils; import org.sonar.api.SonarRuntime; import org.sonar.api.utils.MessageException; @@ -50,8 +51,6 @@ import static org.sonar.server.log.ServerProcessLogging.STARTUP_LOGGER_NAME; import static org.sonar.server.plugins.PluginType.BUNDLED; import static org.sonar.server.plugins.PluginType.EXTERNAL; -import javax.inject.Inject; - public class PluginJarLoader { private static final Logger LOG = Loggers.get(PluginJarLoader.class); diff --git a/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/monitoring/SettingsSection.java b/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/monitoring/SettingsSection.java index 8c87854b66a..9bf64d642ad 100644 --- a/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/monitoring/SettingsSection.java +++ b/server/sonar-webserver-core/src/main/java/org/sonar/server/platform/monitoring/SettingsSection.java @@ -77,7 +77,7 @@ public class SettingsSection implements SystemInfoSection, Global { private void addDefaultNewCodeDefinition(Builder protobuf) { try (DbSession dbSession = dbClient.openSession(false)) { Optional<NewCodePeriodDto> period = dbClient.newCodePeriodDao().selectGlobal(dbSession); - setAttribute(protobuf, "Default New Code Definition", parseDefaultNewCodeDefinition(period)); + setAttribute(protobuf, "Default New Code Definition", parseDefaultNewCodeDefinition(period.orElse(NewCodePeriodDto.defaultInstance()))); } } @@ -95,15 +95,11 @@ public class SettingsSection implements SystemInfoSection, Global { return abbreviate(value, MAX_VALUE_LENGTH); } - private static String parseDefaultNewCodeDefinition(Optional<NewCodePeriodDto> period) { - if (!period.isPresent()) { - return "PREVIOUS_VERSION"; + private static String parseDefaultNewCodeDefinition(NewCodePeriodDto period) { + if (period.getValue() == null) { + return period.getType().name(); } - if (period.get().getValue() == null) { - return period.get().getType().name(); - } - - return period.get().getType().name() + ": " + period.get().getValue(); + return period.getType().name() + ": " + period.getValue(); } } |