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.

CheckstyleProfileExporter.java 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Sonar, open source software quality management tool.
  3. * Copyright (C) 2009 SonarSource SA
  4. * mailto:contact AT sonarsource DOT com
  5. *
  6. * Sonar 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. * Sonar 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
  17. * License along with Sonar; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
  19. */
  20. package org.sonar.plugins.checkstyle;
  21. import com.google.common.collect.ArrayListMultimap;
  22. import com.google.common.collect.ListMultimap;
  23. import org.apache.commons.configuration.BaseConfiguration;
  24. import org.apache.commons.configuration.Configuration;
  25. import org.apache.commons.lang.StringEscapeUtils;
  26. import org.apache.commons.lang.StringUtils;
  27. import org.sonar.api.profiles.ProfileExporter;
  28. import org.sonar.api.profiles.RulesProfile;
  29. import org.sonar.api.resources.Java;
  30. import org.sonar.api.rules.ActiveRule;
  31. import org.sonar.api.rules.ActiveRuleParam;
  32. import org.sonar.api.rules.RuleParam;
  33. import org.sonar.api.utils.SonarException;
  34. import java.io.IOException;
  35. import java.io.Writer;
  36. import java.util.List;
  37. public class CheckstyleProfileExporter extends ProfileExporter {
  38. private Configuration conf;
  39. public CheckstyleProfileExporter(Configuration conf) {
  40. super(CheckstyleConstants.REPOSITORY_KEY, CheckstyleConstants.PLUGIN_NAME);
  41. this.conf = conf;
  42. setSupportedLanguages(Java.KEY);
  43. setMimeType("application/xml");
  44. }
  45. /**
  46. * for unit tests
  47. */
  48. CheckstyleProfileExporter() {
  49. this(new BaseConfiguration());
  50. }
  51. public void exportProfile(RulesProfile profile, Writer writer) {
  52. try {
  53. ListMultimap<String, ActiveRule> activeRulesByConfigKey = arrangeByConfigKey(profile.getActiveRulesByRepository(CheckstyleConstants.REPOSITORY_KEY));
  54. generateXML(writer, activeRulesByConfigKey);
  55. } catch (IOException e) {
  56. throw new SonarException("Fail to export the profile " + profile, e);
  57. }
  58. }
  59. private void generateXML(Writer writer, ListMultimap<String, ActiveRule> activeRulesByConfigKey) throws IOException {
  60. appendXmlHeader(writer);
  61. appendCustomFilters(writer);
  62. appendCheckerModules(writer, activeRulesByConfigKey);
  63. appendTreeWalker(writer, activeRulesByConfigKey);
  64. appendXmlFooter(writer);
  65. }
  66. private void appendXmlHeader(Writer writer) throws IOException {
  67. writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
  68. + "<!DOCTYPE module PUBLIC \"-//Puppy Crawl//DTD Check Configuration 1.2//EN\" \"http://www.puppycrawl.com/dtds/configuration_1_2.dtd\">"
  69. + "<!-- Generated by Sonar -->"
  70. + "<module name=\"Checker\">");
  71. }
  72. private void appendCustomFilters(Writer writer) throws IOException {
  73. String filtersXML = conf.getString(CheckstyleConstants.FILTERS_KEY, CheckstyleConstants.FILTERS_DEFAULT_VALUE);
  74. if (StringUtils.isNotBlank(filtersXML)) {
  75. writer.append(filtersXML);
  76. }
  77. }
  78. private void appendCheckerModules(Writer writer, ListMultimap<String, ActiveRule> activeRulesByConfigKey) throws IOException {
  79. for (String configKey : activeRulesByConfigKey.keySet()) {
  80. if (!isInTreeWalker(configKey)) {
  81. List<ActiveRule> activeRules = activeRulesByConfigKey.get(configKey);
  82. for (ActiveRule activeRule : activeRules) {
  83. appendModule(writer, activeRule, activeRules.size() > 1);
  84. }
  85. }
  86. }
  87. }
  88. private void appendTreeWalker(Writer writer, ListMultimap<String, ActiveRule> activeRulesByConfigKey) throws IOException {
  89. writer.append("<module name=\"TreeWalker\">");
  90. writer.append("<module name=\"FileContentsHolder\"/> ");
  91. for (String configKey : activeRulesByConfigKey.keySet()) {
  92. if (isInTreeWalker(configKey)) {
  93. List<ActiveRule> activeRules = activeRulesByConfigKey.get(configKey);
  94. for (ActiveRule activeRule : activeRules) {
  95. appendModule(writer, activeRule, activeRules.size() > 1);
  96. }
  97. }
  98. }
  99. writer.append("</module>");
  100. }
  101. private void appendXmlFooter(Writer writer) throws IOException {
  102. writer.append("</module>");
  103. }
  104. static boolean isInTreeWalker(String configKey) {
  105. return StringUtils.startsWithIgnoreCase(configKey, "Checker/TreeWalker/");
  106. }
  107. private static ListMultimap<String, ActiveRule> arrangeByConfigKey(List<ActiveRule> activeRules) {
  108. ListMultimap<String, ActiveRule> result = ArrayListMultimap.create();
  109. if (activeRules != null) {
  110. for (ActiveRule activeRule : activeRules) {
  111. result.put(activeRule.getConfigKey(), activeRule);
  112. }
  113. }
  114. return result;
  115. }
  116. private void appendModule(Writer writer, ActiveRule activeRule, boolean manyInstances) throws IOException {
  117. String moduleName = StringUtils.substringAfterLast(activeRule.getConfigKey(), "/");
  118. writer.append("<module name=\"");
  119. StringEscapeUtils.escapeXml(writer, moduleName);
  120. writer.append("\">");
  121. if (manyInstances) {
  122. appendModuleProperty(writer, "id", activeRule.getRuleKey());
  123. }
  124. appendModuleProperty(writer, "severity", CheckstyleSeverityUtils.toSeverity(activeRule.getPriority()));
  125. appendRuleParameters(writer, activeRule);
  126. writer.append("</module>");
  127. }
  128. private void appendRuleParameters(Writer writer, ActiveRule activeRule) throws IOException {
  129. for (RuleParam ruleParam : activeRule.getRule().getParams()) {
  130. String value = activeRule.getParameter(ruleParam.getKey());
  131. if (StringUtils.isNotBlank(value)) {
  132. appendModuleProperty(writer, ruleParam.getKey(), value);
  133. }
  134. }
  135. }
  136. private void appendModuleProperty(Writer writer, String propertyKey, String propertyValue) throws IOException {
  137. if (StringUtils.isNotBlank(propertyValue)) {
  138. writer.append("<property name=\"");
  139. StringEscapeUtils.escapeXml(writer, propertyKey);
  140. writer.append("\" value=\"");
  141. StringEscapeUtils.escapeXml(writer, propertyValue);
  142. writer.append("\"/>");
  143. }
  144. }
  145. }