@@ -1,3 +1,3 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<pmd version="4.2.5" timestamp="2010-09-14T13:20:30.108"> | |||
<pmd version="4.2.5" timestamp="2010-09-15T13:59:35.931"> | |||
</pmd> |
@@ -19,6 +19,12 @@ | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.StringWriter; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import org.sonar.api.BatchExtension; | |||
import org.sonar.api.CoreProperties; | |||
import org.sonar.api.batch.maven.MavenPlugin; | |||
@@ -26,19 +32,14 @@ import org.sonar.api.batch.maven.MavenUtils; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Project; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
public class PmdConfiguration implements BatchExtension { | |||
private PmdRulesRepository pmdRulesRepository; | |||
private PmdProfileExporter pmdProfileExporter; | |||
private RulesProfile rulesProfile; | |||
private Project project; | |||
public PmdConfiguration(PmdRulesRepository pmdRulesRepository, RulesProfile rulesProfile, Project project) { | |||
this.pmdRulesRepository = pmdRulesRepository; | |||
public PmdConfiguration(PmdProfileExporter pmdRulesRepository, RulesProfile rulesProfile, Project project) { | |||
this.pmdProfileExporter = pmdRulesRepository; | |||
this.rulesProfile = rulesProfile; | |||
this.project = project; | |||
} | |||
@@ -60,15 +61,17 @@ public class PmdConfiguration implements BatchExtension { | |||
} | |||
} | |||
if (rulesets == null || rulesets.isEmpty()) { | |||
throw new RuntimeException("The PMD configuration to reuse can not be found. Check the property " + CoreProperties.REUSE_RULES_CONFIGURATION_PROPERTY + " or add the property rulesets/ruleset to the Maven PMD plugin"); | |||
throw new RuntimeException("The PMD configuration to reuse can not be found. Check the property " | |||
+ CoreProperties.REUSE_RULES_CONFIGURATION_PROPERTY + " or add the property rulesets/ruleset to the Maven PMD plugin"); | |||
} | |||
return rulesets; | |||
} | |||
private File saveXmlFile() { | |||
try { | |||
String xml = pmdRulesRepository.exportConfiguration(rulesProfile); | |||
return project.getFileSystem().writeToWorkingDirectory(xml, "pmd.xml"); | |||
StringWriter pmdConfiguration = new StringWriter(); | |||
pmdProfileExporter.exportProfile(rulesProfile, pmdConfiguration); | |||
return project.getFileSystem().writeToWorkingDirectory(pmdConfiguration.toString(), "pmd.xml"); | |||
} catch (IOException e) { | |||
throw new RuntimeException("Fail to save the PMD configuration", e); |
@@ -0,0 +1,67 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import org.sonar.api.rules.RulePriority; | |||
public final class PmdLevelUtils { | |||
private PmdLevelUtils() { | |||
// only static methods | |||
} | |||
public static RulePriority fromLevel(String level) { | |||
if ("1".equals(level)) { | |||
return RulePriority.BLOCKER; | |||
} | |||
if ("2".equals(level)) { | |||
return RulePriority.CRITICAL; | |||
} | |||
if ("3".equals(level)) { | |||
return RulePriority.MAJOR; | |||
} | |||
if ("4".equals(level)) { | |||
return RulePriority.MINOR; | |||
} | |||
if ("5".equals(level)) { | |||
return RulePriority.INFO; | |||
} | |||
return null; | |||
} | |||
public static String toLevel(RulePriority priority) { | |||
if (priority.equals(RulePriority.BLOCKER)) { | |||
return "1"; | |||
} | |||
if (priority.equals(RulePriority.CRITICAL)) { | |||
return "2"; | |||
} | |||
if (priority.equals(RulePriority.MAJOR)) { | |||
return "3"; | |||
} | |||
if (priority.equals(RulePriority.MINOR)) { | |||
return "4"; | |||
} | |||
if (priority.equals(RulePriority.INFO)) { | |||
return "5"; | |||
} | |||
throw new IllegalArgumentException("Level not supported: " + priority); | |||
} | |||
} |
@@ -39,6 +39,16 @@ public class PmdPlugin implements Plugin { | |||
} | |||
public List getExtensions() { | |||
return Arrays.asList(PmdSensor.class, PmdConfiguration.class, PmdExecutor.class, PmdRulesRepository.class); | |||
return Arrays.asList( | |||
PmdSensor.class, | |||
PmdConfiguration.class, | |||
PmdExecutor.class, | |||
PmdRuleRepository.class, | |||
PmdProfileExporter.class, | |||
PmdProfileImporter.class, | |||
SonarWayProfile.class, | |||
SonarWayWithFindbugsProfile.class, | |||
SunConventionsProfile.class | |||
); | |||
} | |||
} |
@@ -32,7 +32,7 @@ import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.ActiveRuleParam; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.utils.SonarException; | |||
import org.sonar.plugins.pmd.xml.Property; | |||
import org.sonar.plugins.pmd.xml.PmdProperty; | |||
import org.sonar.plugins.pmd.xml.PmdRule; | |||
import org.sonar.plugins.pmd.xml.PmdRuleset; | |||
@@ -62,12 +62,12 @@ public class PmdProfileExporter extends ProfileExporter { | |||
for (ActiveRule activeRule : activeRules) { | |||
if (activeRule.getRule().getPluginName().equals(CoreProperties.PMD_PLUGIN)) { | |||
String configKey = activeRule.getRule().getConfigKey(); | |||
PmdRule rule = new PmdRule(configKey, to(activeRule.getPriority())); | |||
List<Property> properties = null; | |||
PmdRule rule = new PmdRule(configKey, PmdLevelUtils.toLevel(activeRule.getPriority())); | |||
List<PmdProperty> properties = null; | |||
if (activeRule.getActiveRuleParams() != null && !activeRule.getActiveRuleParams().isEmpty()) { | |||
properties = new ArrayList<Property>(); | |||
properties = new ArrayList<PmdProperty>(); | |||
for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) { | |||
properties.add(new Property(activeRuleParam.getRuleParam().getKey(), activeRuleParam.getValue())); | |||
properties.add(new PmdProperty(activeRuleParam.getRuleParam().getKey(), activeRuleParam.getValue())); | |||
} | |||
} | |||
rule.setProperties(properties); | |||
@@ -82,27 +82,7 @@ public class PmdProfileExporter extends ProfileExporter { | |||
xstream.setClassLoader(getClass().getClassLoader()); | |||
xstream.processAnnotations(PmdRuleset.class); | |||
xstream.processAnnotations(PmdRule.class); | |||
xstream.processAnnotations(Property.class); | |||
xstream.processAnnotations(PmdProperty.class); | |||
return xstream.toXML(tree); | |||
} | |||
private String to(RulePriority priority) { | |||
if (priority.equals(RulePriority.BLOCKER)) { | |||
return "1"; | |||
} | |||
if (priority.equals(RulePriority.CRITICAL)) { | |||
return "2"; | |||
} | |||
if (priority.equals(RulePriority.MAJOR)) { | |||
return "3"; | |||
} | |||
if (priority.equals(RulePriority.MINOR)) { | |||
return "4"; | |||
} | |||
if (priority.equals(RulePriority.INFO)) { | |||
return "5"; | |||
} | |||
throw new IllegalArgumentException("Level not supported: " + priority); | |||
} | |||
} |
@@ -0,0 +1,90 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import java.io.Reader; | |||
import org.sonar.api.profiles.ProfileImporter; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RuleQuery; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import org.sonar.plugins.pmd.xml.PmdProperty; | |||
import org.sonar.plugins.pmd.xml.PmdRule; | |||
import org.sonar.plugins.pmd.xml.PmdRuleset; | |||
import com.thoughtworks.xstream.XStream; | |||
public class PmdProfileImporter extends ProfileImporter { | |||
private final RuleFinder ruleFinder; | |||
public PmdProfileImporter(RuleFinder ruleFinder) { | |||
super(PmdConstants.REPOSITORY_KEY, PmdConstants.PLUGIN_NAME); | |||
setSupportedLanguages(Java.KEY); | |||
this.ruleFinder = ruleFinder; | |||
} | |||
@Override | |||
public RulesProfile importProfile(Reader pmdConfigurationFile, ValidationMessages messages) { | |||
PmdRuleset pmdRuleset = parsePmdRuleset(pmdConfigurationFile, messages); | |||
RulesProfile profile = createRuleProfile(pmdRuleset, messages); | |||
return profile; | |||
} | |||
protected RulesProfile createRuleProfile(PmdRuleset pmdRuleset, ValidationMessages messages) { | |||
RulesProfile profile = RulesProfile.create(); | |||
for (PmdRule pmdRule : pmdRuleset.getPmdRules()) { | |||
Rule rule = ruleFinder.find(RuleQuery.create().withRepositoryKey(PmdConstants.REPOSITORY_KEY).withConfigKey(pmdRule.getRef())); | |||
if (rule != null) { | |||
ActiveRule activeRule = profile.activateRule(rule, PmdLevelUtils.fromLevel(pmdRule.getPriority())); | |||
if (pmdRule.getProperties() != null) { | |||
for (PmdProperty prop : pmdRule.getProperties()) { | |||
if (rule.getParam(prop.getName()) == null) { | |||
messages.addWarningText("The property '" + prop.getName() + "' is not supported in the pmd rule: " + pmdRule.getRef()); | |||
continue; | |||
} | |||
activeRule.setParameter(prop.getName(), prop.getValue()); | |||
} | |||
} | |||
} else { | |||
messages.addWarningText("Unable to import unknown PMD rule '" + pmdRule.getRef() + "'"); | |||
} | |||
} | |||
return profile; | |||
} | |||
protected PmdRuleset parsePmdRuleset(Reader pmdConfigurationFile, ValidationMessages messages) { | |||
try { | |||
XStream xstream = new XStream(); | |||
xstream.setClassLoader(getClass().getClassLoader()); | |||
xstream.processAnnotations(PmdRuleset.class); | |||
xstream.processAnnotations(PmdRule.class); | |||
xstream.processAnnotations(PmdProperty.class); | |||
return (PmdRuleset) xstream.fromXML(pmdConfigurationFile); | |||
} catch (RuntimeException e) { | |||
messages.addErrorText("The PMD configuration file is not valide: " + e.getMessage()); | |||
return new PmdRuleset(); | |||
} | |||
} | |||
} |
@@ -1,168 +0,0 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import com.thoughtworks.xstream.XStream; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.lang.CharEncoding; | |||
import org.sonar.api.CoreProperties; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.rules.*; | |||
import org.sonar.api.utils.SonarException; | |||
import org.sonar.plugins.pmd.xml.Property; | |||
import org.sonar.plugins.pmd.xml.PmdRule; | |||
import org.sonar.plugins.pmd.xml.PmdRuleset; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
public class PmdRulesRepository extends AbstractImportableRulesRepository<Java, PmdRulePriorityMapper> implements ConfigurationExportable { | |||
public PmdRulesRepository(Java language) { | |||
super(language, new PmdRulePriorityMapper()); | |||
} | |||
@Override | |||
public String getRepositoryResourcesBase() { | |||
return "org/sonar/plugins/pmd"; | |||
} | |||
@Override | |||
public Map<String, String> getBuiltInProfiles() { | |||
Map<String, String> defaults = new HashMap<String, String>(); | |||
defaults.put(RulesProfile.SONAR_WAY_NAME, "profile-sonar-way.xml"); | |||
defaults.put(RulesProfile.SONAR_WAY_FINDBUGS_NAME, "profile-sonar-way.xml"); | |||
defaults.put(RulesProfile.SUN_CONVENTIONS_NAME, "profile-sun-conventions.xml"); | |||
return defaults; | |||
} | |||
public String exportConfiguration(RulesProfile activeProfile) { | |||
PmdRuleset tree = buildModuleTree(activeProfile.getActiveRulesByPlugin(CoreProperties.PMD_PLUGIN), activeProfile.getName()); | |||
String xmlModules = buildXmlFromModuleTree(tree); | |||
return addHeaderToXml(xmlModules); | |||
} | |||
public List<ActiveRule> importConfiguration(String configuration, List<org.sonar.api.rules.Rule> rules) { | |||
List<ActiveRule> activeRules = new ArrayList<ActiveRule>(); | |||
PmdRuleset moduleTree = buildModuleTreeFromXml(configuration); | |||
buildActiveRulesFromModuleTree(moduleTree, activeRules, rules); | |||
return activeRules; | |||
} | |||
protected PmdRuleset buildModuleTree(List<ActiveRule> activeRules) { | |||
return buildModuleTree(activeRules, "Sonar PMD rules"); | |||
} | |||
protected PmdRuleset buildModuleTree(List<ActiveRule> activeRules, String profileName) { | |||
PmdRuleset ruleset = new PmdRuleset(profileName); | |||
for (ActiveRule activeRule : activeRules) { | |||
if (activeRule.getRule().getPluginName().equals(CoreProperties.PMD_PLUGIN)) { | |||
String configKey = activeRule.getRule().getConfigKey(); | |||
PmdRule rule = new PmdRule(configKey, getRulePriorityMapper().to(activeRule.getPriority())); | |||
List<Property> properties = null; | |||
if (activeRule.getActiveRuleParams() != null && !activeRule.getActiveRuleParams().isEmpty()) { | |||
properties = new ArrayList<Property>(); | |||
for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) { | |||
properties.add(new Property(activeRuleParam.getRuleParam().getKey(), activeRuleParam.getValue())); | |||
} | |||
} | |||
rule.setProperties(properties); | |||
ruleset.addRule(rule); | |||
} | |||
} | |||
return ruleset; | |||
} | |||
protected String buildXmlFromModuleTree(PmdRuleset tree) { | |||
XStream xstream = new XStream(); | |||
xstream.setClassLoader(getClass().getClassLoader()); | |||
xstream.processAnnotations(PmdRuleset.class); | |||
xstream.processAnnotations(PmdRule.class); | |||
xstream.processAnnotations(Property.class); | |||
return xstream.toXML(tree); | |||
} | |||
protected String addHeaderToXml(String xmlModules) { | |||
String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; | |||
header += ("<!-- generated by Sonar -->\n"); | |||
return header + xmlModules; | |||
} | |||
protected PmdRuleset buildModuleTreeFromXml(String configuration) { | |||
InputStream inputStream = null; | |||
try { | |||
XStream xstream = new XStream(); | |||
xstream.setClassLoader(getClass().getClassLoader()); | |||
xstream.processAnnotations(PmdRuleset.class); | |||
xstream.processAnnotations(org.sonar.api.rules.Rule.class); | |||
xstream.processAnnotations(Property.class); | |||
inputStream = IOUtils.toInputStream(configuration, CharEncoding.UTF_8); | |||
return (PmdRuleset) xstream.fromXML(inputStream); | |||
} | |||
catch (IOException e) { | |||
throw new SonarException("can't read configuration file", e); | |||
} | |||
finally { | |||
IOUtils.closeQuietly(inputStream); | |||
} | |||
} | |||
protected void buildActiveRulesFromModuleTree(PmdRuleset ruleset, List<ActiveRule> activeRules, List<org.sonar.api.rules.Rule> rules) { | |||
if (ruleset.getRules() != null && !ruleset.getRules().isEmpty()) { | |||
for (PmdRule rule : ruleset.getRules()) { | |||
String ref = rule.getRef(); | |||
for (org.sonar.api.rules.Rule dbRule : rules) { | |||
if (dbRule.getConfigKey().equals(ref)) { | |||
RulePriority rulePriority = getRulePriorityMapper().from(rule.getPriority()); | |||
ActiveRule activeRule = new ActiveRule(null, dbRule, rulePriority); | |||
activeRule.setActiveRuleParams(getActiveRuleParams(rule, dbRule, activeRule)); | |||
activeRules.add(activeRule); | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
private List<ActiveRuleParam> getActiveRuleParams(PmdRule rule, org.sonar.api.rules.Rule dbRule, ActiveRule activeRule) { | |||
List<ActiveRuleParam> activeRuleParams = new ArrayList<ActiveRuleParam>(); | |||
if (rule.getProperties() != null) { | |||
for (Property property : rule.getProperties()) { | |||
if (dbRule.getParams() != null) { | |||
for (RuleParam ruleParam : dbRule.getParams()) { | |||
if (ruleParam.getKey().equals(property.getName())) { | |||
activeRuleParams.add(new ActiveRuleParam(activeRule, ruleParam, property.getValue())); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
return activeRuleParams; | |||
} | |||
} |
@@ -0,0 +1,46 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import java.io.InputStreamReader; | |||
import java.io.Reader; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.utils.ValidationMessages; | |||
public final class SonarWayProfile extends ProfileDefinition { | |||
private final PmdProfileImporter importer; | |||
public SonarWayProfile(PmdProfileImporter importer) { | |||
this.importer = importer; | |||
} | |||
@Override | |||
public RulesProfile createProfile(ValidationMessages messages) { | |||
Reader pmdSonarWayProfile = new InputStreamReader(this.getClass().getResourceAsStream("/org/sonar/plugins/pmd/profile-sonar-way.xml")); | |||
RulesProfile profile = importer.importProfile(pmdSonarWayProfile, messages); | |||
profile.setLanguage(Java.KEY); | |||
profile.setName(RulesProfile.SONAR_WAY_NAME); | |||
return profile; | |||
} | |||
} |
@@ -0,0 +1,44 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.utils.ValidationMessages; | |||
public class SonarWayWithFindbugsProfile extends ProfileDefinition { | |||
private SonarWayProfile sonarWay; | |||
public SonarWayWithFindbugsProfile(SonarWayProfile sonarWay) { | |||
this.sonarWay = sonarWay; | |||
} | |||
@Override | |||
public RulesProfile createProfile(ValidationMessages validationMessages) { | |||
RulesProfile profile = sonarWay.createProfile(validationMessages); | |||
profile.setName(RulesProfile.SONAR_WAY_FINDBUGS_NAME); | |||
profile.setLanguage(Java.KEY); | |||
return profile; | |||
} | |||
} | |||
@@ -0,0 +1,47 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import java.io.InputStreamReader; | |||
import java.io.Reader; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.utils.ValidationMessages; | |||
public final class SunConventionsProfile extends ProfileDefinition { | |||
private final PmdProfileImporter importer; | |||
public SunConventionsProfile(PmdProfileImporter importer) { | |||
this.importer = importer; | |||
} | |||
@Override | |||
public RulesProfile createProfile(ValidationMessages messages) { | |||
Reader pmdSonarWayProfile = new InputStreamReader(this.getClass().getResourceAsStream( | |||
"/org/sonar/plugins/pmd/profile-sun-conventions.xml")); | |||
RulesProfile profile = importer.importProfile(pmdSonarWayProfile, messages); | |||
profile.setName(RulesProfile.SUN_CONVENTIONS_NAME); | |||
profile.setLanguage(Java.KEY); | |||
return profile; | |||
} | |||
} |
@@ -23,7 +23,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
import com.thoughtworks.xstream.annotations.XStreamAsAttribute; | |||
@XStreamAlias("property") | |||
public class Property { | |||
public class PmdProperty { | |||
@XStreamAsAttribute | |||
private String name; | |||
@@ -31,7 +31,7 @@ public class Property { | |||
@XStreamAsAttribute | |||
private String value; | |||
public Property(String name, String value) { | |||
public PmdProperty(String name, String value) { | |||
this.name = name; | |||
this.value = value; | |||
} |
@@ -34,7 +34,7 @@ public class PmdRule implements Comparable<String> { | |||
private String priority; | |||
private List<Property> properties; | |||
private List<PmdProperty> properties = new ArrayList<PmdProperty>(); | |||
@XStreamOmitField | |||
private String description; //NOSONAR unused private field | |||
@@ -62,11 +62,11 @@ public class PmdRule implements Comparable<String> { | |||
return ref; | |||
} | |||
public void setProperties(List<Property> properties) { | |||
public void setProperties(List<PmdProperty> properties) { | |||
this.properties = properties; | |||
} | |||
public List<Property> getProperties() { | |||
public List<PmdProperty> getProperties() { | |||
return properties; | |||
} | |||
@@ -82,9 +82,9 @@ public class PmdRule implements Comparable<String> { | |||
this.priority = priority; | |||
} | |||
public void addProperty(Property property) { | |||
public void addProperty(PmdProperty property) { | |||
if (properties == null) { | |||
properties = new ArrayList<Property>(); | |||
properties = new ArrayList<PmdProperty>(); | |||
} | |||
properties.add(property); | |||
} |
@@ -49,7 +49,7 @@ public class PmdRuleset { | |||
this.description = description; | |||
} | |||
public List<PmdRule> getRules() { | |||
public List<PmdRule> getPmdRules() { | |||
return rules; | |||
} | |||
@@ -19,22 +19,19 @@ | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.Test; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Project; | |||
import org.sonar.api.test.MavenTestUtils; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.junit.Assert.assertThat; | |||
import static org.junit.internal.matchers.IsCollectionContaining.hasItem; | |||
import java.io.File; | |||
import java.io.IOException; | |||
import java.util.List; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.junit.Assert.assertThat; | |||
import static org.junit.internal.matchers.IsCollectionContaining.hasItem; | |||
import static org.mockito.Matchers.anyObject; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import org.apache.commons.io.FileUtils; | |||
import org.junit.Test; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Project; | |||
import org.sonar.api.test.MavenTestUtils; | |||
public class PmdConfigurationTest { | |||
@@ -42,16 +39,13 @@ public class PmdConfigurationTest { | |||
public void writeConfigurationToWorkingDir() throws IOException { | |||
Project project = MavenTestUtils.loadProjectFromPom(getClass(), "writeConfigurationToWorkingDir/pom.xml"); | |||
PmdRulesRepository repository = mock(PmdRulesRepository.class); | |||
when(repository.exportConfiguration((RulesProfile)anyObject())).thenReturn("<conf/>"); | |||
PmdConfiguration configuration = new PmdConfiguration(repository, null, project); | |||
PmdConfiguration configuration = new PmdConfiguration(new PmdProfileExporter(), RulesProfile.create(), project); | |||
List<String> rulesets = configuration.getRulesets(); | |||
assertThat(rulesets.size(), is(1)); | |||
File xmlFile = new File(rulesets.get(0)); | |||
assertThat(xmlFile.exists(), is(true)); | |||
assertThat(FileUtils.readFileToString(xmlFile), is("<conf/>")); | |||
assertThat(FileUtils.readFileToString(xmlFile), is("<ruleset/>")); | |||
} | |||
@Test | |||
@@ -65,7 +59,7 @@ public class PmdConfigurationTest { | |||
assertThat(rulesets, hasItem("ruleset/basic.xml")); | |||
} | |||
@Test(expected=RuntimeException.class) | |||
@Test(expected = RuntimeException.class) | |||
public void failIfConfigurationToReuseDoesNotExist() throws IOException { | |||
Project project = MavenTestUtils.loadProjectFromPom(getClass(), "failIfConfigurationToReuseDoesNotExist/pom.xml"); | |||
@@ -0,0 +1,159 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.hamcrest.Matchers.nullValue; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertThat; | |||
import static org.mockito.Matchers.anyObject; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import java.io.Reader; | |||
import java.io.StringReader; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.rules.RuleQuery; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import org.sonar.plugins.pmd.xml.PmdRuleset; | |||
import org.sonar.test.TestUtils; | |||
public class PmdProfileImporterTest { | |||
private PmdProfileImporter importer; | |||
private ValidationMessages messages; | |||
@Before | |||
public void before() { | |||
messages = ValidationMessages.create(); | |||
RuleFinder finder = createRuleFinder(); | |||
importer = new PmdProfileImporter(finder); | |||
} | |||
@Test | |||
public void testBuildPmdRuleset() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); | |||
PmdRuleset pmdRuleset = importer.parsePmdRuleset(reader, messages); | |||
assertThat(pmdRuleset.getPmdRules().size(), is(3)); | |||
} | |||
@Test | |||
public void testImportingSimpleProfile() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
assertThat(profile.getActiveRules().size(), is(3)); | |||
assertNotNull(profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/ExcessiveImports")); | |||
assertNotNull(profile.getActiveRuleByConfigKey("pmd", "rulesets/design.xml/UseNotifyAllInsteadOfNotify")); | |||
assertThat(messages.hasErrors(), is(false)); | |||
} | |||
@Test | |||
public void testImportingParameters() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
ActiveRule activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/ExcessiveImports"); | |||
assertThat(activeRule.getActiveRuleParams().size(), is(1)); | |||
assertThat(activeRule.getParameter("max"), is("30")); | |||
} | |||
@Test | |||
public void testImportingDefaultPriority() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
ActiveRule activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/ExcessiveImports"); | |||
assertThat(activeRule.getPriority(), is(RulePriority.BLOCKER)); // reuse the rule default priority | |||
} | |||
@Test | |||
public void testImportingPriority() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
ActiveRule activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/design.xml/UseNotifyAllInsteadOfNotify"); | |||
assertThat(activeRule.getPriority(), is(RulePriority.MINOR)); | |||
activeRule = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/CouplingBetweenObjects"); | |||
assertThat(activeRule.getPriority(), is(RulePriority.CRITICAL)); | |||
} | |||
@Test | |||
public void testImportingPmdConfigurationWithUnknownNodes() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/complex-with-unknown-nodes.xml")); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
assertThat(profile.getActiveRules().size(), is(3)); | |||
} | |||
@Test | |||
public void testUnsupportedProperty() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
ActiveRule check = profile.getActiveRuleByConfigKey("pmd", "rulesets/coupling.xml/CouplingBetweenObjects"); | |||
assertThat(check.getParameter("threshold"), nullValue()); | |||
assertThat(messages.getWarnings().size(), is(1)); | |||
} | |||
@Test | |||
public void testUnvalidXML() { | |||
Reader reader = new StringReader("not xml"); | |||
importer.importProfile(reader, messages); | |||
assertThat(messages.getErrors().size(), is(1)); | |||
} | |||
@Test | |||
public void testImportingUnknownRules() { | |||
Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); | |||
importer = new PmdProfileImporter(mock(RuleFinder.class)); | |||
RulesProfile profile = importer.importProfile(reader, messages); | |||
assertThat(profile.getActiveRules().size(), is(0)); | |||
assertThat(messages.getWarnings().size(), is(3)); | |||
} | |||
private RuleFinder createRuleFinder() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.find((RuleQuery) anyObject())).thenAnswer(new Answer<Rule>() { | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
RuleQuery query = (RuleQuery) iom.getArguments()[0]; | |||
Rule rule = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey()) | |||
.setConfigKey(query.getConfigKey()).setPriority(RulePriority.BLOCKER); | |||
if (rule.getConfigKey().equals("rulesets/coupling.xml/ExcessiveImports")) { | |||
rule.createParameter("max"); | |||
} | |||
return rule; | |||
} | |||
}); | |||
return ruleFinder; | |||
} | |||
} |
@@ -1,396 +0,0 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import com.thoughtworks.xstream.converters.ConversionException; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.lang.CharEncoding; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import org.sonar.api.CoreProperties; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.ActiveRuleParam; | |||
import org.sonar.api.rules.RuleParam; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.plugins.pmd.xml.Property; | |||
import org.sonar.plugins.pmd.xml.PmdRule; | |||
import org.sonar.plugins.pmd.xml.PmdRuleset; | |||
import org.sonar.test.TestUtils; | |||
import org.xml.sax.SAXException; | |||
import java.io.IOException; | |||
import java.io.InputStream; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import static org.hamcrest.CoreMatchers.is; | |||
import static org.hamcrest.Matchers.notNullValue; | |||
import static org.junit.Assert.*; | |||
public class PmdRulesRepositoryTest { | |||
private PmdRulesRepository repository; | |||
@Before | |||
public void setup() { | |||
repository = new PmdRulesRepository(new Java()); | |||
} | |||
@Test | |||
public void rulesAreDefinedWithTheDefaultSonarXmlFormat() { | |||
List<org.sonar.api.rules.Rule> rules = repository.getInitialReferential(); | |||
assertTrue(rules.size() > 0); | |||
for (org.sonar.api.rules.Rule rule : rules) { | |||
assertNotNull(rule.getKey()); | |||
assertNotNull(rule.getDescription()); | |||
assertNotNull(rule.getConfigKey()); | |||
assertNotNull(rule.getName()); | |||
} | |||
} | |||
@Test | |||
public void shouldImportconfigurationWithUtf8Character() { | |||
RulesProfile rulesProfile = repository.loadProvidedProfile("profile", "test_xml_utf8.xml"); | |||
assertThat(rulesProfile, notNullValue()); | |||
String value = rulesProfile.getActiveRules().get(0).getActiveRuleParams().get(0).getValue(); | |||
assertThat(value, is("\u00E9")); | |||
} | |||
@Test | |||
public void shouldBuildModuleWithProperties() { | |||
org.sonar.api.rules.Rule dbRule = new org.sonar.api.rules.Rule(); | |||
dbRule.setConfigKey("rulesets/design.xml/CloseResource"); | |||
dbRule.setPluginName(CoreProperties.PMD_PLUGIN); | |||
RuleParam ruleParam = new RuleParam(dbRule, "types", null, null); | |||
ActiveRule activeRule = new ActiveRule(null, dbRule, RulePriority.MAJOR); | |||
activeRule.setActiveRuleParams(Arrays.asList(new ActiveRuleParam(activeRule, ruleParam, "Connection,Statement,ResultSet"))); | |||
PmdRuleset ruleset = repository.buildModuleTree(Arrays.asList(activeRule)); | |||
assertThat(ruleset.getRules().size(), is(1)); | |||
PmdRule rule = ruleset.getRules().get(0); | |||
assertThat(rule.getRef(), is("rulesets/design.xml/CloseResource")); | |||
assertThat(rule.getProperties().size(), is(1)); | |||
assertThat(rule.getPriority(), is("3")); | |||
Property property = rule.getProperties().get(0); | |||
assertThat(property.getName(), is("types")); | |||
assertThat(property.getValue(), is("Connection,Statement,ResultSet")); | |||
} | |||
@Test | |||
public void shouldBuildManyModules() { | |||
org.sonar.api.rules.Rule rule1 = new org.sonar.api.rules.Rule(); | |||
rule1.setPluginName(CoreProperties.PMD_PLUGIN); | |||
rule1.setConfigKey("rulesets/design.xml/CloseResource"); | |||
ActiveRule activeRule1 = new ActiveRule(null, rule1, RulePriority.MAJOR); | |||
org.sonar.api.rules.Rule rule2 = new org.sonar.api.rules.Rule(); | |||
rule2.setPluginName(CoreProperties.PMD_PLUGIN); | |||
rule2.setConfigKey("rulesets/braces.xml/IfElseStmtsMustUseBraces"); | |||
ActiveRule activeRule2 = new ActiveRule(null, rule2, RulePriority.MAJOR); | |||
PmdRuleset ruleset = repository.buildModuleTree(Arrays.asList(activeRule1, activeRule2)); | |||
assertThat(ruleset.getRules().size(), is(2)); | |||
assertThat(ruleset.getRules().get(0).getRef(), is("rulesets/design.xml/CloseResource")); | |||
assertThat(ruleset.getRules().get(1).getRef(), is("rulesets/braces.xml/IfElseStmtsMustUseBraces")); | |||
} | |||
@Test | |||
public void shouldBuilModuleTreeFromXml() throws IOException { | |||
InputStream input = getClass().getResourceAsStream("/org/sonar/plugins/pmd/test_module_tree.xml"); | |||
PmdRuleset ruleset = repository.buildModuleTreeFromXml(IOUtils.toString(input)); | |||
assertThat(ruleset.getRules().size(), is(3)); | |||
PmdRule rule1 = ruleset.getRules().get(0); | |||
assertThat(rule1.getRef(), is("rulesets/coupling.xml/CouplingBetweenObjects")); | |||
assertThat(rule1.getPriority(), is("2")); | |||
assertThat(rule1.getProperties().size(), is(1)); | |||
Property module1Property = rule1.getProperties().get(0); | |||
assertThat(module1Property.getName(), is("threshold")); | |||
assertThat(module1Property.getValue(), is("20")); | |||
PmdRule rule2 = ruleset.getRules().get(1); | |||
assertThat(rule2.getRef(), is("rulesets/coupling.xml/ExcessiveImports")); | |||
assertThat(rule2.getPriority(), is("3")); | |||
assertThat(rule2.getProperties().size(), is(1)); | |||
Property module2Property = rule2.getProperties().get(0); | |||
assertThat(module2Property.getName(), is("max")); | |||
assertThat(module2Property.getValue(), is("30")); | |||
PmdRule rule3 = ruleset.getRules().get(2); | |||
assertThat(rule3.getRef(), is("rulesets/design.xml/UseNotifyAllInsteadOfNotify")); | |||
assertThat(rule3.getPriority(), is("4")); | |||
assertNull(rule3.getProperties()); | |||
} | |||
@Test | |||
public void shouldBuilModuleTreeFromXmlInUtf8() throws IOException { | |||
InputStream input = getClass().getResourceAsStream("/org/sonar/plugins/pmd/test_xml_utf8.xml"); | |||
PmdRuleset ruleset = repository.buildModuleTreeFromXml(IOUtils.toString(input, CharEncoding.UTF_8)); | |||
PmdRule rule1 = ruleset.getRules().get(0); | |||
assertThat(rule1.getRef(), is("rulesets/coupling.xml/CouplingBetweenObjects")); | |||
assertThat(rule1.getProperties().get(0).getValue(), is("\u00E9")); | |||
} | |||
@Test | |||
public void shouldBuilXmlFromModuleTree() throws IOException, SAXException { | |||
PmdRuleset ruleset = buildModuleTreeFixture(); | |||
String xml = repository.buildXmlFromModuleTree(ruleset); | |||
assertXmlAreSimilar(xml, "test_module_tree.xml"); | |||
} | |||
@Test | |||
public void shouldImportConfiguration() throws IOException { | |||
final List<org.sonar.api.rules.Rule> inputRules = buildRulesFixture(); | |||
List<ActiveRule> activeRulesExpected = buildActiveRulesFixture(inputRules); | |||
InputStream input = getClass().getResourceAsStream("/org/sonar/plugins/pmd/test_module_tree.xml"); | |||
List<ActiveRule> results = repository.importConfiguration(IOUtils.toString(input), inputRules); | |||
assertThat(results.size(), is(activeRulesExpected.size())); | |||
assertActiveRulesAreEquals(results, activeRulesExpected); | |||
} | |||
@Test | |||
public void shouldImportPmdLevelsAsSonarLevels() throws IOException { | |||
InputStream input = getClass().getResourceAsStream("/org/sonar/plugins/pmd/PmdRulesRepositoryTest/shouldImportPmdLevelsAsSonarLevels.xml"); | |||
final List<org.sonar.api.rules.Rule> rules = buildRulesFixture(); | |||
List<ActiveRule> results = repository.importConfiguration(IOUtils.toString(input), rules); | |||
assertThat(results.size(), is(3)); | |||
assertThat(results.get(0).getPriority(), is(RulePriority.MAJOR)); | |||
assertThat(results.get(1).getPriority(), is(RulePriority.MINOR)); | |||
assertThat(results.get(2).getPriority(), is(RulePriority.INFO)); | |||
} | |||
@Test | |||
public void shouldImportWithDefaultRuleLevelWhenNoExplicitPriority() throws IOException { | |||
InputStream input = getClass().getResourceAsStream("/org/sonar/plugins/pmd/PmdRulesRepositoryTest/shouldImportWithDefaultRuleLevelWhenNoExplicitPriority.xml"); | |||
final List<org.sonar.api.rules.Rule> rules = buildRulesFixture(); | |||
List<ActiveRule> results = repository.importConfiguration(IOUtils.toString(input), rules); | |||
assertThat(results.size(), is(1)); | |||
assertThat(results.get(0).getPriority(), is(RulePriority.MAJOR)); | |||
} | |||
@Test | |||
public void shouldImportConfigurationContainingDataToExcludeWithoutException() throws IOException { | |||
shouldImportConfiguration("test_xml_with_data_to_exclude.xml"); | |||
} | |||
// See http://jira.codehaus.org/browse/XSTR-448 for details | |||
@Test(expected = ConversionException.class) | |||
public void shouldFailToImportConfigurationContainingClassParamBecauseOfXStreamLimitation() throws IOException { | |||
shouldImportConfiguration("test_xml_with_class_param.xml"); | |||
} | |||
@Test | |||
public void shouldBuildActiveRulesFromModuleTree() { | |||
final List<org.sonar.api.rules.Rule> inputRules = buildRulesFixture(); | |||
List<ActiveRule> activeRulesExpected = buildActiveRulesFixture(inputRules); | |||
List<ActiveRule> activeRules = new ArrayList<ActiveRule>(); | |||
PmdRuleset ruleset = buildModuleTreeFixture(); | |||
repository.buildActiveRulesFromModuleTree(ruleset, activeRules, inputRules); | |||
assertThat(activeRulesExpected.size(), is(activeRules.size())); | |||
assertActiveRulesAreEquals(activeRulesExpected, activeRules); | |||
} | |||
@Test | |||
public void shouldProvideProfiles() { | |||
List<RulesProfile> profiles = repository.getProvidedProfiles(); | |||
assertThat(profiles.size(), is(3)); | |||
RulesProfile profile1 = profiles.get(0); | |||
assertThat(profile1.getName(), is(RulesProfile.SONAR_WAY_NAME)); | |||
assertTrue(profile1.getActiveRules().size() + "", profile1.getActiveRules().size() > 30); | |||
RulesProfile profile2 = profiles.get(1); | |||
assertThat(profile2.getName(), is(RulesProfile.SONAR_WAY_FINDBUGS_NAME)); | |||
assertTrue(profile2.getActiveRules().size() + "", profile2.getActiveRules().size() > 30); | |||
RulesProfile profile3 = profiles.get(2); | |||
assertThat(profile3.getName(), is(RulesProfile.SUN_CONVENTIONS_NAME)); | |||
assertTrue(profile3.getActiveRules().size() + "", profile3.getActiveRules().size() > 1); | |||
} | |||
@Test | |||
public void shouldAddHeaderToXml() throws IOException, SAXException { | |||
String xml = repository.addHeaderToXml("<ruleset/>"); | |||
assertXmlAreSimilar(xml, "test_header.xml"); | |||
} | |||
@Test | |||
public void shouldBuildOnlyOneModuleWhenNoPmdActiveRules() { | |||
org.sonar.api.rules.Rule rule1 = new org.sonar.api.rules.Rule(); | |||
rule1.setPluginName("not-a-pmd-plugin"); | |||
ActiveRule activeRule1 = new ActiveRule(null, rule1, RulePriority.CRITICAL); | |||
org.sonar.api.rules.Rule rule2 = new org.sonar.api.rules.Rule(); | |||
rule2.setPluginName("not-a-pmd-plugin"); | |||
ActiveRule activeRule2 = new ActiveRule(null, rule1, RulePriority.CRITICAL); | |||
PmdRuleset tree = repository.buildModuleTree(Arrays.asList(activeRule1, activeRule2)); | |||
assertThat(tree.getRules().size(), is(0)); | |||
} | |||
@Test | |||
public void shouldBuildOnlyOneModuleWhenNoActiveRules() { | |||
PmdRuleset tree = repository.buildModuleTree(Collections.<ActiveRule>emptyList()); | |||
assertThat(tree.getRules().size(), is(0)); | |||
} | |||
@Test | |||
public void shouldBuildTwoModulesEvenIfSameTwoRulesActivated() { | |||
org.sonar.api.rules.Rule dbRule1 = new org.sonar.api.rules.Rule(); | |||
dbRule1.setPluginName(CoreProperties.PMD_PLUGIN); | |||
dbRule1.setConfigKey("rulesets/coupling.xml/CouplingBetweenObjects"); | |||
ActiveRule activeRule1 = new ActiveRule(null, dbRule1, RulePriority.CRITICAL); | |||
org.sonar.api.rules.Rule dbRule2 = new org.sonar.api.rules.Rule(); | |||
dbRule2.setPluginName(CoreProperties.PMD_PLUGIN); | |||
dbRule2.setConfigKey("rulesets/coupling.xml/CouplingBetweenObjects"); | |||
ActiveRule activeRule2 = new ActiveRule(null, dbRule2, RulePriority.CRITICAL); | |||
PmdRuleset tree = repository.buildModuleTree(Arrays.asList(activeRule1, activeRule2)); | |||
assertThat(tree.getRules().size(), is(2)); | |||
PmdRule rule1 = tree.getRules().get(0); | |||
assertThat(rule1.getRef(), is("rulesets/coupling.xml/CouplingBetweenObjects")); | |||
PmdRule rule2 = tree.getRules().get(1); | |||
assertThat(rule2.getRef(), is("rulesets/coupling.xml/CouplingBetweenObjects")); | |||
} | |||
// ------------------------------------------------------------------------ | |||
// -- Private methods | |||
// ------------------------------------------------------------------------ | |||
private void assertXmlAreSimilar(String xml, String xmlFileToFind) throws IOException, SAXException { | |||
InputStream input = getClass().getResourceAsStream("/org/sonar/plugins/pmd/" + xmlFileToFind); | |||
String xmlToFind = IOUtils.toString(input); | |||
TestUtils.assertSimilarXml(xmlToFind, xml); | |||
} | |||
private PmdRuleset buildModuleTreeFixture() { | |||
PmdRuleset ruleset = new PmdRuleset(); | |||
ruleset.setDescription("Sonar PMD rules"); | |||
PmdRule rule1 = new PmdRule("rulesets/coupling.xml/CouplingBetweenObjects", "2"); | |||
rule1.addProperty(new Property("threshold", "20")); | |||
ruleset.addRule(rule1); | |||
PmdRule rule2 = new PmdRule("rulesets/coupling.xml/ExcessiveImports", "3"); | |||
rule2.addProperty(new Property("max", "30")); | |||
ruleset.addRule(rule2); | |||
PmdRule rule3 = new PmdRule("rulesets/design.xml/UseNotifyAllInsteadOfNotify", "4"); | |||
ruleset.addRule(rule3); | |||
return ruleset; | |||
} | |||
private List<org.sonar.api.rules.Rule> buildRulesFixture() { | |||
final org.sonar.api.rules.Rule rule1 = new org.sonar.api.rules.Rule("Coupling Between Objects", "CouplingBetweenObjects", | |||
"rulesets/coupling.xml/CouplingBetweenObjects", null, CoreProperties.PMD_PLUGIN, null); | |||
RuleParam ruleParam1 = new RuleParam(rule1, "threshold", null, "i"); | |||
rule1.setParams(Arrays.asList(ruleParam1)); | |||
final org.sonar.api.rules.Rule rule2 = new org.sonar.api.rules.Rule("Excessive Imports", "ExcessiveImports", | |||
"rulesets/coupling.xml/ExcessiveImports", null, CoreProperties.PMD_PLUGIN, null); | |||
RuleParam ruleParam2 = new RuleParam(rule2, "max", null, "i"); | |||
rule2.setParams(Arrays.asList(ruleParam2)); | |||
final org.sonar.api.rules.Rule rule3 = new org.sonar.api.rules.Rule("Use Notify All Instead Of Notify", "UseNotifyAllInsteadOfNotify", | |||
"rulesets/design.xml/UseNotifyAllInsteadOfNotify", null, CoreProperties.PMD_PLUGIN, null); | |||
final org.sonar.api.rules.Rule rule4 = new org.sonar.api.rules.Rule("Class names should always begin with an upper case character.", "ClassNamingConventions", | |||
"rulesets/naming.xml/ClassNamingConventions", null, CoreProperties.PMD_PLUGIN, null); | |||
return Arrays.asList(rule1, rule2, rule3, rule4); | |||
} | |||
private List<ActiveRule> buildActiveRulesFixture(List<org.sonar.api.rules.Rule> rules) { | |||
List<ActiveRule> activeRules = new ArrayList<ActiveRule>(); | |||
ActiveRule activeRule1 = new ActiveRule(null, rules.get(0), RulePriority.CRITICAL); | |||
activeRule1.setActiveRuleParams(Arrays.asList(new ActiveRuleParam(activeRule1, rules.get(0).getParams().get(0), "20"))); | |||
activeRules.add(activeRule1); | |||
ActiveRule activeRule2 = new ActiveRule(null, rules.get(1), RulePriority.MAJOR); | |||
activeRule2.setActiveRuleParams(Arrays.asList(new ActiveRuleParam(activeRule2, rules.get(1).getParams().get(0), "30"))); | |||
activeRules.add(activeRule2); | |||
ActiveRule activeRule3 = new ActiveRule(null, rules.get(2), RulePriority.MINOR); | |||
activeRules.add(activeRule3); | |||
return activeRules; | |||
} | |||
private void assertActiveRulesAreEquals(List<ActiveRule> activeRules1, List<ActiveRule> activeRules2) { | |||
for (int i = 0; i < activeRules1.size(); i++) { | |||
ActiveRule activeRule1 = activeRules1.get(i); | |||
ActiveRule activeRule2 = activeRules2.get(i); | |||
assertTrue(activeRule1.getRule().equals(activeRule2.getRule())); | |||
assertTrue(activeRule1.getPriority().equals(activeRule2.getPriority())); | |||
assertEquals(activeRule1.getActiveRuleParams().size(), (activeRule2.getActiveRuleParams().size())); | |||
for (int j = 0; j < activeRule1.getActiveRuleParams().size(); j++) { | |||
ActiveRuleParam activeRuleParam1 = activeRule1.getActiveRuleParams().get(j); | |||
ActiveRuleParam activeRuleParam2 = activeRule2.getActiveRuleParams().get(j); | |||
assertTrue(activeRuleParam1.getRuleParam().equals(activeRuleParam2.getRuleParam()) | |||
&& activeRuleParam1.getValue().equals(activeRuleParam2.getValue())); | |||
} | |||
} | |||
} | |||
public void shouldImportConfiguration(String configurationFile) throws IOException { | |||
final List<org.sonar.api.rules.Rule> inputRules = buildRulesFixture(); | |||
List<ActiveRule> activeRulesExpected = buildActiveRulesFixture(inputRules); | |||
InputStream input = getClass().getResourceAsStream("/org/sonar/plugins/pmd/" + configurationFile); | |||
List<ActiveRule> results = repository.importConfiguration(IOUtils.toString(input), inputRules); | |||
assertThat(results.size(), is(activeRulesExpected.size())); | |||
assertActiveRulesAreEquals(results, activeRulesExpected); | |||
} | |||
@Test | |||
public void shouldUseTheProfileNameWhenBuildingTheRulesSet() { | |||
PmdRuleset tree = repository.buildModuleTree(Collections.<ActiveRule>emptyList(), "aprofile"); | |||
assertThat(tree.getDescription(), is("aprofile")); | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import static org.hamcrest.core.Is.is; | |||
import static org.hamcrest.number.OrderingComparisons.greaterThan; | |||
import static org.junit.Assert.assertThat; | |||
import static org.mockito.Matchers.anyObject; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.rules.RuleQuery; | |||
import org.sonar.api.utils.ValidationMessages; | |||
public class SonarWayProfileTest { | |||
@Test | |||
public void create() { | |||
ProfileDefinition sonarWay = new SonarWayProfile(createPmdProfileImporter()); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RulesProfile profile = sonarWay.createProfile(validation); | |||
assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).size(), greaterThan(1)); | |||
assertThat(validation.hasErrors(), is(false)); | |||
} | |||
private PmdProfileImporter createPmdProfileImporter() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.find((RuleQuery) anyObject())).thenAnswer(new Answer<Rule>() { | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
RuleQuery query = (RuleQuery) iom.getArguments()[0]; | |||
Rule rule = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey()) | |||
.setConfigKey(query.getConfigKey()).setPriority(RulePriority.BLOCKER); | |||
return rule; | |||
} | |||
}); | |||
PmdProfileImporter importer = new PmdProfileImporter(ruleFinder); | |||
return importer; | |||
} | |||
} |
@@ -0,0 +1,65 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import static org.hamcrest.core.Is.is; | |||
import static org.hamcrest.number.OrderingComparisons.greaterThan; | |||
import static org.junit.Assert.assertThat; | |||
import static org.mockito.Matchers.anyObject; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.rules.RuleQuery; | |||
import org.sonar.api.utils.ValidationMessages; | |||
public class SonarWayWithFindbugsProfileTest { | |||
@Test | |||
public void create() { | |||
SonarWayWithFindbugsProfile sonarWayWithFindbugs = new SonarWayWithFindbugsProfile(new SonarWayProfile(createPmdProfileImporter())); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RulesProfile profile = sonarWayWithFindbugs.createProfile(validation); | |||
assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).size(), greaterThan(1)); | |||
assertThat(validation.hasErrors(), is(false)); | |||
} | |||
private PmdProfileImporter createPmdProfileImporter() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.find((RuleQuery) anyObject())).thenAnswer(new Answer<Rule>() { | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
RuleQuery query = (RuleQuery) iom.getArguments()[0]; | |||
Rule rule = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey()) | |||
.setConfigKey(query.getConfigKey()).setPriority(RulePriority.BLOCKER); | |||
return rule; | |||
} | |||
}); | |||
PmdProfileImporter importer = new PmdProfileImporter(ruleFinder); | |||
return importer; | |||
} | |||
} |
@@ -0,0 +1,65 @@ | |||
/* | |||
* Sonar, open source software quality management tool. | |||
* Copyright (C) 2009 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* Sonar 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. | |||
* | |||
* Sonar 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 Sonar; if not, write to the Free Software | |||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 | |||
*/ | |||
package org.sonar.plugins.pmd; | |||
import static org.hamcrest.core.Is.is; | |||
import static org.hamcrest.number.OrderingComparisons.greaterThan; | |||
import static org.junit.Assert.assertThat; | |||
import static org.mockito.Matchers.anyObject; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.rules.RuleQuery; | |||
import org.sonar.api.utils.ValidationMessages; | |||
public class SunConventionsProfileTest { | |||
@Test | |||
public void create() { | |||
SunConventionsProfile sunConvention = new SunConventionsProfile(createPmdProfileImporter()); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RulesProfile profile = sunConvention.createProfile(validation); | |||
assertThat(profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY).size(), greaterThan(1)); | |||
assertThat(validation.hasErrors(), is(false)); | |||
} | |||
private PmdProfileImporter createPmdProfileImporter() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.find((RuleQuery) anyObject())).thenAnswer(new Answer<Rule>() { | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
RuleQuery query = (RuleQuery) iom.getArguments()[0]; | |||
Rule rule = Rule.create(query.getRepositoryKey(), query.getConfigKey(), "Rule name - " + query.getConfigKey()) | |||
.setConfigKey(query.getConfigKey()).setPriority(RulePriority.BLOCKER); | |||
return rule; | |||
} | |||
}); | |||
PmdProfileImporter importer = new PmdProfileImporter(ruleFinder); | |||
return importer; | |||
} | |||
} |
@@ -1,15 +0,0 @@ | |||
<ruleset> | |||
<description>Sonar PMD rules</description> | |||
<rule ref="rulesets/coupling.xml/ExcessiveImports"> | |||
<priority>3</priority> | |||
<properties> | |||
<property name="max" value="30"/> | |||
</properties> | |||
</rule> | |||
<rule ref="rulesets/design.xml/UseNotifyAllInsteadOfNotify"> | |||
<priority>4</priority> | |||
</rule> | |||
<rule ref="rulesets/naming.xml/ClassNamingConventions"> | |||
<priority>5</priority> | |||
</rule> | |||
</ruleset> |
@@ -1,7 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
<ruleset xmlns="http://pmd.sf.net/ruleset/1.0.0" name="pmd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |||
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd" | |||
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"> | |||
<description>test</description> | |||
<rule ref="rulesets/naming.xml/ClassNamingConventions"/> | |||
</ruleset> |
@@ -1,3 +1,4 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<ruleset> | |||
<description>Sonar PMD rules</description> | |||
<rule ref="rulesets/coupling.xml/CouplingBetweenObjects"> | |||
@@ -7,7 +8,6 @@ | |||
</properties> | |||
</rule> | |||
<rule ref="rulesets/coupling.xml/ExcessiveImports"> | |||
<priority>3</priority> | |||
<properties> | |||
<property name="max" value="30"/> | |||
</properties> |
@@ -1,3 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- Sonar PMD rules generated configuration --> | |||
<ruleset/> |
@@ -1,11 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- Sonar PMD rules generated configuration --> | |||
<ruleset> | |||
<description>Sonar PMD rules</description> | |||
<rule ref="rulesets/coupling.xml/CouplingBetweenObjects"> | |||
<priority>1</priority> | |||
<properties> | |||
<property name="threshold" value="é"/> | |||
</properties> | |||
</rule> | |||
</ruleset> |
@@ -1,28 +0,0 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<!-- Sonar PMD rules generated configuration --> | |||
<ruleset language="My language" name="My name"> | |||
<description>Sonar PMD rules</description> | |||
<exclude-pattern>to exclude</exclude-pattern> | |||
<include-pattern>to include</include-pattern> | |||
<rule ref="rulesets/coupling.xml/CouplingBetweenObjects" externalInfoUrl="String" typeResolution="false" dfa="true" | |||
name="ID_1" class="NMTOKEN" message="String" since="String"> | |||
<description>rule description</description> | |||
<priority>2</priority> | |||
<properties> | |||
<property name="threshold" value="20"/> | |||
</properties> | |||
<exclude name="NMTOKEN"/> | |||
<example>an example</example> | |||
</rule> | |||
<rule ref="rulesets/coupling.xml/ExcessiveImports"> | |||
<priority>3</priority> | |||
<properties> | |||
<property name="max" value="30" pluginname="plugin name" description="property description"/> | |||
</properties> | |||
</rule> | |||
<rule ref="rulesets/design.xml/UseNotifyAllInsteadOfNotify"> | |||
<priority>4</priority> | |||
</rule> | |||
</ruleset> | |||