Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

ProjectTrackerBaseLazyInput.java 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2019 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.ce.task.projectanalysis.issue;
  21. import java.util.ArrayList;
  22. import java.util.Collection;
  23. import java.util.Date;
  24. import java.util.List;
  25. import java.util.Map;
  26. import java.util.Optional;
  27. import java.util.Set;
  28. import java.util.function.Function;
  29. import java.util.stream.Collectors;
  30. import java.util.stream.Stream;
  31. import org.apache.commons.lang.StringUtils;
  32. import org.sonar.api.resources.Qualifiers;
  33. import org.sonar.ce.task.projectanalysis.analysis.AnalysisMetadataHolder;
  34. import org.sonar.ce.task.projectanalysis.component.Component;
  35. import org.sonar.ce.task.projectanalysis.component.ReportModulesPath;
  36. import org.sonar.core.issue.DefaultIssue;
  37. import org.sonar.core.issue.IssueChangeContext;
  38. import org.sonar.db.DbClient;
  39. import org.sonar.db.DbSession;
  40. import org.sonar.db.component.ComponentDto;
  41. import org.sonar.server.issue.IssueFieldsSetter;
  42. import static org.apache.commons.lang.StringUtils.trimToEmpty;
  43. class ProjectTrackerBaseLazyInput extends BaseInputFactory.BaseLazyInput {
  44. private AnalysisMetadataHolder analysisMetadataHolder;
  45. private ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues;
  46. private DbClient dbClient;
  47. private IssueFieldsSetter issueUpdater;
  48. private ComponentIssuesLoader issuesLoader;
  49. private ReportModulesPath reportModulesPath;
  50. ProjectTrackerBaseLazyInput(AnalysisMetadataHolder analysisMetadataHolder, ComponentsWithUnprocessedIssues componentsWithUnprocessedIssues, DbClient dbClient,
  51. IssueFieldsSetter issueUpdater, ComponentIssuesLoader issuesLoader, ReportModulesPath reportModulesPath, Component component) {
  52. super(dbClient, component, null);
  53. this.analysisMetadataHolder = analysisMetadataHolder;
  54. this.componentsWithUnprocessedIssues = componentsWithUnprocessedIssues;
  55. this.dbClient = dbClient;
  56. this.issueUpdater = issueUpdater;
  57. this.issuesLoader = issuesLoader;
  58. this.reportModulesPath = reportModulesPath;
  59. }
  60. @Override
  61. protected List<DefaultIssue> loadIssues() {
  62. List<DefaultIssue> result = new ArrayList<>();
  63. try (DbSession dbSession = dbClient.openSession(false)) {
  64. Set<String> dirOrModulesUuidsWithIssues = dbClient.issueDao().selectModuleAndDirComponentUuidsOfOpenIssuesForProjectUuid(dbSession, component.getUuid());
  65. if (!dirOrModulesUuidsWithIssues.isEmpty()) {
  66. Map<String, String> pathByModuleKey = reportModulesPath.get();
  67. // Migrate issues that were previously on modules or directories to the root project
  68. Map<String, ComponentDto> modulesByUuid = dbClient.componentDao().selectProjectAndModulesFromProjectKey(dbSession, component.getDbKey(), true)
  69. .stream().collect(Collectors.toMap(ComponentDto::uuid, Function.identity()));
  70. List<ComponentDto> dirOrModulesWithIssues = dbClient.componentDao().selectByUuids(dbSession, dirOrModulesUuidsWithIssues);
  71. dirOrModulesWithIssues.forEach(c -> {
  72. List<DefaultIssue> issuesOnModuleOrDir = issuesLoader.loadOpenIssues(c.uuid());
  73. String moduleOrDirProjectRelativePath = c.qualifier().equals(Qualifiers.MODULE) ? buildModuleProjectRelativePath(pathByModuleKey, c)
  74. : buildDirectoryProjectRelativePath(pathByModuleKey, c, modulesByUuid.get(c.moduleUuid()));
  75. result.addAll(migrateIssuesToTheRoot(issuesOnModuleOrDir, moduleOrDirProjectRelativePath));
  76. componentsWithUnprocessedIssues.remove(c.uuid());
  77. });
  78. }
  79. result.addAll(issuesLoader.loadOpenIssues(effectiveUuid));
  80. return result;
  81. }
  82. }
  83. private static String buildDirectoryProjectRelativePath(Map<String, String> pathByModuleKey, ComponentDto c, ComponentDto parentModule) {
  84. String moduleProjectRelativePath = buildModuleProjectRelativePath(pathByModuleKey, parentModule);
  85. return Stream.of(moduleProjectRelativePath, c.path())
  86. .map(StringUtils::trimToNull)
  87. .filter(s -> s != null && !"/".equals(s))
  88. .collect(Collectors.joining("/"));
  89. }
  90. private static String buildModuleProjectRelativePath(Map<String, String> pathByModuleKey, ComponentDto parentModule) {
  91. return Optional.ofNullable(pathByModuleKey.get(parentModule.getKey()))
  92. // If module is not in the scanner report, we can't guess the path accurately. Fallback on what we have in DB
  93. .orElse(trimToEmpty(parentModule.path()));
  94. }
  95. private Collection<? extends DefaultIssue> migrateIssuesToTheRoot(List<DefaultIssue> issuesOnModule, String modulePath) {
  96. for (DefaultIssue i : issuesOnModule) {
  97. // changes the issue's component uuid, add a change and set issue as changed to enforce it is persisted to DB
  98. IssueChangeContext context = IssueChangeContext.createUser(new Date(analysisMetadataHolder.getAnalysisDate()), null);
  99. if (StringUtils.isNotBlank(modulePath)) {
  100. issueUpdater.setMessage(i, "[" + modulePath + "] " + i.getMessage(), context);
  101. }
  102. issueUpdater.setIssueMoved(i, component.getUuid(), context);
  103. // other fields (such as module, modulePath, componentKey) are read-only and set/reset for consistency only
  104. i.setComponentKey(component.getKey());
  105. i.setModuleUuid(null);
  106. i.setModuleUuidPath(null);
  107. }
  108. return issuesOnModule;
  109. }
  110. }