You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IssueIteratorForSingleChunk.java 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2023 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.server.issue.index;
  21. import com.google.common.base.CharMatcher;
  22. import com.google.common.base.Splitter;
  23. import java.util.Collection;
  24. import java.util.HashMap;
  25. import java.util.Iterator;
  26. import java.util.Optional;
  27. import javax.annotation.CheckForNull;
  28. import javax.annotation.Nullable;
  29. import org.apache.ibatis.cursor.Cursor;
  30. import org.sonar.api.resources.Qualifiers;
  31. import org.sonar.api.resources.Scopes;
  32. import org.sonar.api.rules.CleanCodeAttribute;
  33. import org.sonar.api.rules.RuleType;
  34. import org.sonar.db.DatabaseUtils;
  35. import org.sonar.db.DbClient;
  36. import org.sonar.db.DbSession;
  37. import org.sonar.db.issue.IndexedIssueDto;
  38. import org.sonar.server.security.SecurityStandards;
  39. import static com.google.common.base.Preconditions.checkArgument;
  40. import static org.sonar.api.utils.DateUtils.longToDate;
  41. import static org.sonar.db.rule.RuleDto.deserializeSecurityStandardsString;
  42. import static org.sonar.server.security.SecurityStandards.fromSecurityStandards;
  43. /**
  44. * Scrolls over table ISSUES and reads documents to populate
  45. * the issues index
  46. */
  47. class IssueIteratorForSingleChunk implements IssueIterator {
  48. static final Splitter STRING_LIST_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings();
  49. private final DbSession session;
  50. private final Iterator<IndexedIssueDto> iterator;
  51. IssueIteratorForSingleChunk(DbClient dbClient, @Nullable String branchUuid, @Nullable Collection<String> issueKeys) {
  52. checkArgument(issueKeys == null || issueKeys.size() <= DatabaseUtils.PARTITION_SIZE_FOR_ORACLE,
  53. "Cannot search for more than " + DatabaseUtils.PARTITION_SIZE_FOR_ORACLE + " issue keys at once. Please provide the keys in smaller chunks.");
  54. this.session = dbClient.openSession(false);
  55. try {
  56. Cursor<IndexedIssueDto> indexCursor = dbClient.issueDao().scrollIssuesForIndexation(session, branchUuid, issueKeys);
  57. iterator = indexCursor.iterator();
  58. } catch (Exception e) {
  59. session.close();
  60. throw new IllegalStateException("Fail to prepare SQL request to select all issues", e);
  61. }
  62. }
  63. @Override
  64. public boolean hasNext() {
  65. return iterator.hasNext();
  66. }
  67. @Override
  68. public IssueDoc next() {
  69. return toIssueDoc(iterator.next());
  70. }
  71. private static IssueDoc toIssueDoc(IndexedIssueDto indexedIssueDto) {
  72. IssueDoc doc = new IssueDoc(new HashMap<>(30));
  73. String key = indexedIssueDto.getIssueKey();
  74. // all the fields must be present, even if value is null
  75. doc.setKey(key);
  76. doc.setAssigneeUuid(indexedIssueDto.getAssignee());
  77. doc.setLine(indexedIssueDto.getLine());
  78. doc.setResolution(indexedIssueDto.getResolution());
  79. doc.setSeverity(indexedIssueDto.getSeverity());
  80. String cleanCodeAttributeCategory = Optional.ofNullable(indexedIssueDto.getCleanCodeAttribute())
  81. .map(CleanCodeAttribute::valueOf)
  82. .map(CleanCodeAttribute::getAttributeCategory)
  83. .map(Enum::name)
  84. .orElse(null);
  85. doc.setCleanCodeAttributeCategory(cleanCodeAttributeCategory);
  86. doc.setStatus(indexedIssueDto.getStatus());
  87. doc.setIssueStatus(indexedIssueDto.getIssueStatus());
  88. doc.setEffort(indexedIssueDto.getEffort());
  89. doc.setAuthorLogin(indexedIssueDto.getAuthorLogin());
  90. doc.setFuncCloseDate(longToDate(indexedIssueDto.getIssueCloseDate()));
  91. doc.setFuncCreationDate(longToDate(indexedIssueDto.getIssueCreationDate()));
  92. doc.setFuncUpdateDate(longToDate(indexedIssueDto.getIssueUpdateDate()));
  93. doc.setRuleUuid(indexedIssueDto.getRuleUuid());
  94. doc.setLanguage(indexedIssueDto.getLanguage());
  95. doc.setComponentUuid(indexedIssueDto.getComponentUuid());
  96. String scope = indexedIssueDto.getScope();
  97. String filePath = extractFilePath(indexedIssueDto.getPath(), scope);
  98. doc.setFilePath(filePath);
  99. doc.setDirectoryPath(extractDirPath(doc.filePath(), scope));
  100. String branchUuid = indexedIssueDto.getBranchUuid();
  101. boolean isMainBranch = indexedIssueDto.isMain();
  102. String projectUuid = indexedIssueDto.getProjectUuid();
  103. doc.setBranchUuid(branchUuid);
  104. doc.setIsMainBranch(isMainBranch);
  105. doc.setProjectUuid(projectUuid);
  106. String tags = indexedIssueDto.getTags();
  107. doc.setTags(STRING_LIST_SPLITTER.splitToList(tags == null ? "" : tags));
  108. doc.setType(RuleType.valueOf(indexedIssueDto.getIssueType()));
  109. doc.setImpacts(indexedIssueDto.getEffectiveImpacts());
  110. SecurityStandards securityStandards = fromSecurityStandards(deserializeSecurityStandardsString(indexedIssueDto.getSecurityStandards()));
  111. SecurityStandards.SQCategory sqCategory = securityStandards.getSqCategory();
  112. doc.setOwaspTop10(securityStandards.getOwaspTop10());
  113. doc.setOwaspTop10For2021(securityStandards.getOwaspTop10For2021());
  114. doc.setPciDss32(securityStandards.getPciDss32());
  115. doc.setPciDss40(securityStandards.getPciDss40());
  116. doc.setOwaspAsvs40(securityStandards.getOwaspAsvs40());
  117. doc.setCwe(securityStandards.getCwe());
  118. doc.setSansTop25(securityStandards.getSansTop25());
  119. doc.setSonarSourceSecurityCategory(sqCategory);
  120. doc.setVulnerabilityProbability(sqCategory.getVulnerability());
  121. doc.setScope(Qualifiers.UNIT_TEST_FILE.equals(indexedIssueDto.getQualifier()) ? IssueScope.TEST : IssueScope.MAIN);
  122. doc.setIsNewCodeReference(indexedIssueDto.isNewCodeReferenceIssue());
  123. String codeVariants = indexedIssueDto.getCodeVariants();
  124. doc.setCodeVariants(STRING_LIST_SPLITTER.splitToList(codeVariants == null ? "" : codeVariants));
  125. return doc;
  126. }
  127. @CheckForNull
  128. private static String extractDirPath(@Nullable String filePath, String scope) {
  129. if (filePath != null) {
  130. if (Scopes.DIRECTORY.equals(scope)) {
  131. return filePath;
  132. }
  133. int lastSlashIndex = CharMatcher.anyOf("/").lastIndexIn(filePath);
  134. if (lastSlashIndex > 0) {
  135. return filePath.substring(0, lastSlashIndex);
  136. }
  137. return "/";
  138. }
  139. return null;
  140. }
  141. @CheckForNull
  142. private static String extractFilePath(@Nullable String filePath, String scope) {
  143. // On modules, the path contains the relative path of the module starting from its parent, and in E/S we're only interested in the
  144. // path
  145. // of files and directories.
  146. // That's why the file path should be null on modules and projects.
  147. if (filePath != null && !Scopes.PROJECT.equals(scope)) {
  148. return filePath;
  149. }
  150. return null;
  151. }
  152. @Override
  153. public void close() {
  154. session.close();
  155. }
  156. }