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.

DefaultActiveRulesLoader.java 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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.scanner.rule;
  21. import java.io.IOException;
  22. import java.io.InputStream;
  23. import java.util.HashMap;
  24. import java.util.LinkedList;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.stream.Collectors;
  28. import org.apache.commons.io.IOUtils;
  29. import org.sonar.api.batch.rule.LoadedActiveRule;
  30. import org.sonar.api.impl.utils.ScannerUtils;
  31. import org.sonar.api.rule.RuleKey;
  32. import org.sonar.api.utils.DateUtils;
  33. import org.sonar.api.utils.MessageException;
  34. import org.sonar.scanner.bootstrap.ScannerWsClient;
  35. import org.sonarqube.ws.Rules;
  36. import org.sonarqube.ws.Rules.Active;
  37. import org.sonarqube.ws.Rules.Active.Param;
  38. import org.sonarqube.ws.Rules.ActiveList;
  39. import org.sonarqube.ws.Rules.Rule;
  40. import org.sonarqube.ws.Rules.SearchResponse;
  41. import org.sonarqube.ws.client.GetRequest;
  42. public class DefaultActiveRulesLoader implements ActiveRulesLoader {
  43. private static final String RULES_SEARCH_URL = "/api/rules/search.protobuf?" +
  44. "f=repo,name,severity,lang,internalKey,templateKey,params,actives,createdAt,updatedAt,deprecatedKeys&activation=true";
  45. private final ScannerWsClient wsClient;
  46. public DefaultActiveRulesLoader(ScannerWsClient wsClient) {
  47. this.wsClient = wsClient;
  48. }
  49. @Override
  50. public List<LoadedActiveRule> load(String qualityProfileKey) {
  51. List<LoadedActiveRule> ruleList = new LinkedList<>();
  52. int page = 1;
  53. int pageSize = 500;
  54. long loaded = 0;
  55. while (true) {
  56. GetRequest getRequest = new GetRequest(getUrl(qualityProfileKey, page, pageSize));
  57. SearchResponse response = loadFromStream(wsClient.call(getRequest).contentStream());
  58. List<LoadedActiveRule> pageRules = readPage(response);
  59. ruleList.addAll(pageRules);
  60. loaded += response.getPaging().getPageSize();
  61. if (response.getPaging().getTotal() <= loaded) {
  62. break;
  63. }
  64. page++;
  65. }
  66. return ruleList;
  67. }
  68. private static String getUrl(String qualityProfileKey, int page, int pageSize) {
  69. StringBuilder builder = new StringBuilder(1024);
  70. builder.append(RULES_SEARCH_URL);
  71. builder.append("&qprofile=").append(ScannerUtils.encodeForUrl(qualityProfileKey));
  72. builder.append("&ps=").append(pageSize);
  73. builder.append("&p=").append(page);
  74. return builder.toString();
  75. }
  76. private static SearchResponse loadFromStream(InputStream is) {
  77. try {
  78. return SearchResponse.parseFrom(is);
  79. } catch (IOException e) {
  80. throw new IllegalStateException("Failed to load quality profiles", e);
  81. } finally {
  82. IOUtils.closeQuietly(is);
  83. }
  84. }
  85. private static List<LoadedActiveRule> readPage(SearchResponse response) {
  86. List<LoadedActiveRule> loadedRules = new LinkedList<>();
  87. List<Rule> rulesList = response.getRulesList();
  88. Map<String, ActiveList> actives = response.getActives().getActivesMap();
  89. for (Rule r : rulesList) {
  90. ActiveList activeList = actives.get(r.getKey());
  91. if (activeList == null) {
  92. throw MessageException.of("Elasticsearch indices have become inconsistent. Consider re-indexing. " +
  93. "Check documentation for more information https://docs.sonarqube.org/latest/setup/troubleshooting");
  94. }
  95. Active active = activeList.getActiveList(0);
  96. LoadedActiveRule loadedRule = new LoadedActiveRule();
  97. loadedRule.setRuleKey(RuleKey.parse(r.getKey()));
  98. loadedRule.setName(r.getName());
  99. loadedRule.setSeverity(active.getSeverity());
  100. loadedRule.setCreatedAt(DateUtils.dateToLong(DateUtils.parseDateTime(active.getCreatedAt())));
  101. loadedRule.setUpdatedAt(DateUtils.dateToLong(DateUtils.parseDateTime(active.getUpdatedAt())));
  102. loadedRule.setLanguage(r.getLang());
  103. loadedRule.setInternalKey(r.getInternalKey());
  104. if (r.hasTemplateKey()) {
  105. RuleKey templateRuleKey = RuleKey.parse(r.getTemplateKey());
  106. loadedRule.setTemplateRuleKey(templateRuleKey.rule());
  107. }
  108. Map<String, String> params = new HashMap<>();
  109. for (Rules.Rule.Param param : r.getParams().getParamsList()) {
  110. params.put(param.getKey(), param.getDefaultValue());
  111. }
  112. // overrides defaultValue if the key is the same
  113. for (Param param : active.getParamsList()) {
  114. params.put(param.getKey(), param.getValue());
  115. }
  116. loadedRule.setParams(params);
  117. loadedRule.setDeprecatedKeys(r.getDeprecatedKeys().getDeprecatedKeyList()
  118. .stream()
  119. .map(RuleKey::parse)
  120. .collect(Collectors.toSet()));
  121. loadedRules.add(loadedRule);
  122. }
  123. return loadedRules;
  124. }
  125. }