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