]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-16316 DAO to fetch report issues from DB
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Thu, 28 Apr 2022 21:22:34 +0000 (16:22 -0500)
committersonartech <sonartech@sonarsource.com>
Wed, 25 May 2022 20:03:15 +0000 (20:03 +0000)
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

13 files changed:
server/sonar-db-dao/src/main/java/org/sonar/db/DaoModule.java
server/sonar-db-dao/src/main/java/org/sonar/db/DbClient.java
server/sonar-db-dao/src/main/java/org/sonar/db/MyBatis.java
server/sonar-db-dao/src/main/java/org/sonar/db/newcodeperiod/NewCodePeriodDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/report/IssueFindingDto.java [new file with mode: 0644]
server/sonar-db-dao/src/main/java/org/sonar/db/report/RegulatoryReportDao.java [new file with mode: 0644]
server/sonar-db-dao/src/main/java/org/sonar/db/report/RegulatoryReportMapper.java [new file with mode: 0644]
server/sonar-db-dao/src/main/java/org/sonar/db/report/package-info.java [new file with mode: 0644]
server/sonar-db-dao/src/main/resources/org/sonar/db/report/RegulatoryReportMapper.xml [new file with mode: 0644]
server/sonar-db-dao/src/test/java/org/sonar/db/report/RegulatoryReportDaoTest.java [new file with mode: 0644]
server/sonar-db-dao/src/testFixtures/java/org/sonar/db/issue/IssueDbTester.java
server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/PluginJarLoader.java
server/sonar-webserver-core/src/main/java/org/sonar/server/platform/monitoring/SettingsSection.java

index c0c487f2f342e72749ee037076331cc1bf37052f..01893f01de6ed93ae14fcea665531a16f84a210e 100644 (file)
@@ -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,
index d545de23ae5563cda7c68d4aa171bb231f802587..b883f7623d2103ab3bb9df45c9acd21dbf6e5df9 100644 (file)
@@ -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;
   }
index 462ea745804ef72eb32d2b59056236af6be09a8f..112752428a3f6c51c4a0b1dd62d360894fe81932 100644 (file)
@@ -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,
index c59df0ef22128e9d605e431dc8074e1064955449..82b2d02702b12437fcb9e7d087985f8ec51c6a97 100644 (file)
@@ -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 (file)
index 0000000..b1fdfe9
--- /dev/null
@@ -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 (file)
index 0000000..8cd4a7c
--- /dev/null
@@ -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 (file)
index 0000000..1a75e22
--- /dev/null
@@ -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 (file)
index 0000000..35263a2
--- /dev/null
@@ -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 (file)
index 0000000..84787bd
--- /dev/null
@@ -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 (file)
index 0000000..81411f3
--- /dev/null
@@ -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());
+  }
+}
index 595183d387dfe4bdd7f1a3ae1aceb3bf01fb962d..e57b916648999eff5284f080d30fbe5be3a55247 100644 (file)
@@ -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();
+  }
+
 }
index 0f2eb7ccab9eaa99f5cd27da5b1f2970c4662549..a39998be1321b6cee10597927824274e3b6a560c 100644 (file)
@@ -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);
 
index 8c87854b66ad672fa13d28a3458ace18d30b90af..9bf64d642ad1a9b33b467ec04c1e917c7559e448 100644 (file)
@@ -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();
   }
 }