/*
* Sonar C# Plugin :: FxCop
* Copyright (C) 2010 Jose Chillan, Alexandre Victoor and SonarSource
* dev@sonar.codehaus.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.plugins.csharp.fxcop.profiles;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.profiles.ProfileExporter;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.utils.SonarException;
import org.sonar.plugins.csharp.api.CSharpConstants;
import org.sonar.plugins.csharp.fxcop.FxCopConstants;
import org.sonar.plugins.csharp.fxcop.profiles.utils.FxCopRule;
/**
* Class that allows to export a Sonar profile into a FxCop rule definition file.
*/
public class FxCopProfileExporter extends ProfileExporter {
private static final String FXCOP_PROJECT_FILE_HEADER = "fxcop-project-file-header.txt";
private static final String FXCOP_PROJECT_FILE_FOOTER = "fxcop-project-file-footer.txt";
public FxCopProfileExporter() {
super(FxCopConstants.REPOSITORY_KEY, FxCopConstants.REPOSITORY_NAME);
setSupportedLanguages(CSharpConstants.LANGUAGE_KEY);
setMimeType("application/xml");
}
/**
* {@inheritDoc}
*/
@Override
public void exportProfile(RulesProfile profile, Writer writer) {
try {
printIntoWriter(writer, FXCOP_PROJECT_FILE_HEADER);
printRules(profile, writer);
printIntoWriter(writer, FXCOP_PROJECT_FILE_FOOTER);
} catch (IOException e) {
throw new SonarException("Error while generating the FxCop profile to export: " + profile, e);
}
}
private void printRules(RulesProfile profile, Writer writer) throws IOException {
List<ActiveRule> activeRules = profile.getActiveRulesByRepository(FxCopConstants.REPOSITORY_KEY);
List<FxCopRule> rules = transformIntoFxCopRules(activeRules);
// We group the rules by RuleFile names
Map<String, List<FxCopRule>> rulesByFile = groupFxCopRulesByRuleFileName(rules);
// And then print out each rule
for (String fileName : rulesByFile.keySet()) {
printRuleFile(writer, rulesByFile, fileName);
}
}
private void printRuleFile(Writer writer, Map<String, List<FxCopRule>> rulesByFile, String fileName) throws IOException {
writer.append(" <RuleFile AllRulesEnabled=\"False\" Enabled=\"True\" Name=\"");
StringEscapeUtils.escapeXml(writer, fileName);
writer.append("\">\n");
for (FxCopRule fxCopRule : rulesByFile.get(fileName)) {
printRule(writer, fxCopRule);
}
writer.append(" </RuleFile>\n");
}
private void printRule(Writer writer, FxCopRule fxCopRule) throws IOException {
writer.append(" <Rule Enabled=\"True\" Name=\"");
StringEscapeUtils.escapeXml(writer, fxCopRule.getName());
writer.append("\" SonarPriority=\"");
StringEscapeUtils.escapeXml(writer, fxCopRule.getPriority());
writer.append("\"/>\n");
}
private List<FxCopRule> transformIntoFxCopRules(List<ActiveRule> activeRulesByPlugin) {
List<FxCopRule> result = new ArrayList<FxCopRule>();
for (ActiveRule activeRule : activeRulesByPlugin) {
// Extracts the rule's information
Rule rule = activeRule.getRule();
String configKey = rule.getConfigKey();
String fileName = StringUtils.substringAfter(configKey, "@");
String name = StringUtils.substringBefore(configKey, "@");
// Creates the FxCop rule
FxCopRule fxCopRule = new FxCopRule();
fxCopRule.setEnabled(true);
fxCopRule.setFileName(fileName);
fxCopRule.setName(name);
RulePriority priority = activeRule.getSeverity();
if (priority != null) {
fxCopRule.setPriority(priority.name().toLowerCase());
}
result.add(fxCopRule);
}
return result;
}
private Map<String, List<FxCopRule>> groupFxCopRulesByRuleFileName(List<FxCopRule> rules) {
Map<String, List<FxCopRule>> rulesByFile = new HashMap<String, List<FxCopRule>>();
for (FxCopRule fxCopRule : rules) {
String fileName = fxCopRule.getFileName();
List<FxCopRule> rulesList = rulesByFile.get(fileName);
if (rulesList == null) {
rulesList = new ArrayList<FxCopRule>();
rulesByFile.put(fileName, rulesList);
}
rulesList.add(fxCopRule);
}
return rulesByFile;
}
private void printIntoWriter(Writer writer, String fileName) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(FxCopProfileExporter.class.getResourceAsStream(fileName)));
try {
String line = reader.readLine();
while (line != null) {
writer.append(line);
writer.append("\n");
line = reader.readLine();
}
reader.close();
} finally {
IOUtils.closeQuietly(reader);
}
}
}