Skip to content

Commit

Permalink
Merge pull request #98 from jensgerdes/bugfix/sonarqube_7.6_compatibi…
Browse files Browse the repository at this point in the history
…lity

Fixes #81
  • Loading branch information
jensgerdes authored Mar 19, 2019
2 parents 7b2fe4c + d89e804 commit 655d590
Show file tree
Hide file tree
Showing 18 changed files with 600 additions and 406 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
<groupId>org.sonarsource.sonarqube</groupId>
<artifactId>sonar-plugin-api</artifactId>
<scope>provided</scope>
<version>7.5</version>
<version>7.6</version>
<exclusions>
<exclusion>
<groupId>xml-apis</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
Expand All @@ -40,31 +41,30 @@
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.fs.InputFile.Type;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.config.Configuration;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.plugins.java.api.JavaResourceLocator;
import org.sonar.plugins.pmd.profile.PmdProfileExporter;
import org.sonar.plugins.pmd.xml.PmdRuleSet;
import org.sonar.plugins.pmd.xml.PmdRuleSets;

@ScannerSide
public class PmdExecutor {

private static final Logger LOGGER = Loggers.get(PmdExecutor.class);

private final FileSystem fs;
private final RulesProfile rulesProfile;
private final PmdProfileExporter pmdProfileExporter;
private final ActiveRules rulesProfile;
private final PmdConfiguration pmdConfiguration;
private final JavaResourceLocator javaResourceLocator;
private final Configuration settings;

public PmdExecutor(FileSystem fileSystem, RulesProfile rulesProfile, PmdProfileExporter pmdProfileExporter,
public PmdExecutor(FileSystem fileSystem, ActiveRules rulesProfile,
PmdConfiguration pmdConfiguration, JavaResourceLocator javaResourceLocator, Configuration settings) {
this.fs = fileSystem;
this.rulesProfile = rulesProfile;
this.pmdProfileExporter = pmdProfileExporter;
this.pmdConfiguration = pmdConfiguration;
this.javaResourceLocator = javaResourceLocator;
this.settings = settings;
Expand Down Expand Up @@ -135,7 +135,7 @@ private void executeRules(PmdTemplate pmdFactory, RuleContext ruleContext, Itera
}

private RuleSets createRuleSets(String repositoryKey) {
String rulesXml = pmdProfileExporter.exportProfile(repositoryKey, rulesProfile);
String rulesXml = dumpXml(rulesProfile, repositoryKey);
File ruleSetFile = pmdConfiguration.dumpXmlRuleSet(repositoryKey, rulesXml);
String ruleSetFilePath = ruleSetFile.getAbsolutePath();
RuleSetFactory ruleSetFactory = new RuleSetFactory();
Expand All @@ -147,6 +147,14 @@ private RuleSets createRuleSets(String repositoryKey) {
}
}

private String dumpXml(ActiveRules rulesProfile, String repositoryKey) {
final StringWriter writer = new StringWriter();
final PmdRuleSet ruleSet = PmdRuleSets.from(rulesProfile, repositoryKey);
ruleSet.writeTo(writer);

return writer.toString();
}

PmdTemplate createPmdTemplate(URLClassLoader classLoader) {
return PmdTemplate.create(getSourceVersion(), classLoader, fs.encoding());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,18 @@
import org.sonar.api.batch.fs.FilePredicates;
import org.sonar.api.batch.fs.FileSystem;
import org.sonar.api.batch.fs.InputFile.Type;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
import org.sonar.api.profiles.RulesProfile;

public class PmdSensor implements Sensor {
private final RulesProfile profile;
private final ActiveRules profile;
private final PmdExecutor executor;
private final PmdViolationRecorder pmdViolationRecorder;
private final FileSystem fs;

public PmdSensor(RulesProfile profile, PmdExecutor executor, PmdViolationRecorder pmdViolationRecorder, FileSystem fs) {
public PmdSensor(ActiveRules profile, PmdExecutor executor, PmdViolationRecorder pmdViolationRecorder, FileSystem fs) {
this.profile = profile;
this.executor = executor;
this.pmdViolationRecorder = pmdViolationRecorder;
Expand All @@ -51,7 +51,7 @@ private boolean hasFilesToCheck(Type type, String repositoryKey) {
final boolean hasMatchingFiles = fs.hasFiles(predicates.and(
predicates.hasLanguage(PmdConstants.LANGUAGE_KEY),
predicates.hasType(type)));
return hasMatchingFiles && !profile.getActiveRulesByRepository(repositoryKey).isEmpty();
return hasMatchingFiles && !profile.findByRepository(repositoryKey).isEmpty();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,17 @@
*/
package org.sonar.plugins.pmd.profile;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;
import org.jdom.CDATA;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.sonar.api.batch.ScannerSide;
import org.sonar.api.profiles.ProfileExporter;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.ActiveRuleParam;
import org.sonar.plugins.pmd.PmdConstants;
import org.sonar.plugins.pmd.PmdLevelUtils;
import org.sonar.plugins.pmd.xml.PmdProperty;
import org.sonar.plugins.pmd.xml.PmdRule;
import org.sonar.plugins.pmd.xml.PmdRuleSet;
import org.sonar.plugins.pmd.xml.PmdRuleSets;

@ScannerSide
/**
* ServerSide component that is able to export all currently active PMD rules as XML.
*/
public class PmdProfileExporter extends ProfileExporter {

private static final String CONTENT_TYPE_APPLICATION_XML = "application/xml";
Expand All @@ -54,130 +40,15 @@ public PmdProfileExporter() {
setMimeType(CONTENT_TYPE_APPLICATION_XML);
}

private static void addRuleProperties(ActiveRule activeRule, PmdRule pmdRule) {
if ((activeRule.getActiveRuleParams() != null) && !activeRule.getActiveRuleParams().isEmpty()) {
List<PmdProperty> properties = new ArrayList<>();
for (ActiveRuleParam activeRuleParam : activeRule.getActiveRuleParams()) {
properties.add(new PmdProperty(activeRuleParam.getRuleParam().getKey(), activeRuleParam.getValue()));
}
pmdRule.setProperties(properties);
}
}

static void processXPathRule(String sonarRuleKey, PmdRule rule) {
if (PmdConstants.XPATH_CLASS.equals(rule.getRef())) {
rule.setRef(null);
PmdProperty xpathMessage = rule.getProperty(PmdConstants.XPATH_MESSAGE_PARAM);
if (xpathMessage == null) {
throw new IllegalArgumentException("Property '" + PmdConstants.XPATH_MESSAGE_PARAM + "' should be set for PMD rule " + sonarRuleKey);
}
rule.setMessage(xpathMessage.getValue());
rule.removeProperty(PmdConstants.XPATH_MESSAGE_PARAM);
PmdProperty xpathExp = rule.getProperty(PmdConstants.XPATH_EXPRESSION_PARAM);
if (xpathExp == null) {
throw new IllegalArgumentException("Property '" + PmdConstants.XPATH_EXPRESSION_PARAM + "' should be set for PMD rule " + sonarRuleKey);
}
xpathExp.setCdataValue(xpathExp.getValue());
rule.setClazz(PmdConstants.XPATH_CLASS);
rule.setLanguage(PmdConstants.LANGUAGE_KEY);
rule.setName(sonarRuleKey);
}
}

private static void exportPmdRulesetToXml(PmdRuleSet pmdRuleset, Writer writer, String profileName) {
Element eltRuleset = new Element("ruleset");
addAttribute(eltRuleset, "name", pmdRuleset.getName());
addChild(eltRuleset, "description", pmdRuleset.getDescription());
for (PmdRule pmdRule : pmdRuleset.getPmdRules()) {
Element eltRule = new Element("rule");
addAttribute(eltRule, "ref", pmdRule.getRef());
addAttribute(eltRule, "class", pmdRule.getClazz());
addAttribute(eltRule, "message", pmdRule.getMessage());
addAttribute(eltRule, "name", pmdRule.getName());
addAttribute(eltRule, "language", pmdRule.getLanguage());
addChild(eltRule, "priority", String.valueOf(pmdRule.getPriority()));
if (pmdRule.hasProperties()) {
Element ruleProperties = processRuleProperties(pmdRule);
if (ruleProperties.getContentSize() > 0) {
eltRule.addContent(ruleProperties);
}
}
eltRuleset.addContent(eltRule);
}
XMLOutputter serializer = new XMLOutputter(Format.getPrettyFormat());
try {
serializer.output(new Document(eltRuleset), writer);
} catch (IOException e) {
throw new IllegalStateException("An exception occurred while generating the PMD configuration file from profile: " + profileName, e);
}
}

private static Element processRuleProperties(PmdRule pmdRule) {
Element eltProperties = new Element("properties");
for (PmdProperty prop : pmdRule.getProperties()) {
if (isPropertyValueNotEmpty(prop)) {
Element eltProperty = new Element("property");
eltProperty.setAttribute("name", prop.getName());
if (prop.isCdataValue()) {
Element eltValue = new Element("value");
eltValue.addContent(new CDATA(prop.getCdataValue()));
eltProperty.addContent(eltValue);
} else {
eltProperty.setAttribute("value", prop.getValue());
}
eltProperties.addContent(eltProperty);
}
}
return eltProperties;
}

private static boolean isPropertyValueNotEmpty(PmdProperty prop) {
if (prop.isCdataValue()) {
return StringUtils.isNotEmpty(prop.getCdataValue());
}
return StringUtils.isNotEmpty(prop.getValue());
}

private static void addChild(Element elt, String name, @Nullable String text) {
if (text != null) {
elt.addContent(new Element(name).setText(text));
}
}

private static void addAttribute(Element elt, String name, @Nullable String value) {
if (value != null) {
elt.setAttribute(name, value);
}
}

@Override
public void exportProfile(RulesProfile profile, Writer writer) {
String profileName = profile.getName();
PmdRuleSet tree = createPmdRuleset(PmdConstants.REPOSITORY_KEY, profile.getActiveRulesByRepository(PmdConstants.REPOSITORY_KEY));
exportPmdRulesetToXml(tree, writer, profileName);
}

public String exportProfile(String repositoryKey, RulesProfile profile) {
String profileName = profile.getName();
PmdRuleSet tree = createPmdRuleset(repositoryKey, profile.getActiveRulesByRepository(repositoryKey));
StringWriter stringWriter = new StringWriter();
exportPmdRulesetToXml(tree, stringWriter, profileName);
return stringWriter.toString();
}
final PmdRuleSet tree = PmdRuleSets.from(profile, PmdConstants.REPOSITORY_KEY);

private PmdRuleSet createPmdRuleset(String repositoryKey, List<ActiveRule> activeRules) {
PmdRuleSet ruleset = new PmdRuleSet();
ruleset.setName(repositoryKey);
ruleset.setDescription(String.format("Sonar Profile: %s", repositoryKey));
for (ActiveRule activeRule : activeRules) {
if (activeRule.getRule().getRepositoryKey().equals(repositoryKey)) {
String configKey = activeRule.getRule().getConfigKey();
PmdRule rule = new PmdRule(configKey, PmdLevelUtils.toLevel(activeRule.getSeverity()));
addRuleProperties(activeRule, rule);
ruleset.addRule(rule);
processXPathRule(activeRule.getRuleKey(), rule);
}
try {
tree.writeTo(writer);
} catch (IllegalStateException e) {
throw new IllegalStateException("An exception occurred while generating the PMD configuration file from profile: " + profile.getName(), e);
}
return ruleset;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ private void setParameters(ActiveRule activeRule, PmdRule pmdRule, Rule rule, Va

@Override
public RulesProfile importProfile(Reader pmdConfigurationFile, ValidationMessages messages) {
PmdRuleSet pmdRuleset = PmdRuleSets.parse(pmdConfigurationFile, messages);
PmdRuleSet pmdRuleset = PmdRuleSets.from(pmdConfigurationFile, messages);
RulesProfile profile = RulesProfile.create();
for (PmdRule pmdRule : pmdRuleset.getPmdRules()) {
String ruleClassName = pmdRule.getClazz();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import java.util.List;
import javax.annotation.Nullable;

import org.sonar.plugins.pmd.PmdConstants;

public class PmdRule {

private String ref;
Expand Down Expand Up @@ -123,4 +125,26 @@ public void setLanguage(String language) {
this.language = language;
}

public void processXpath(String sonarRuleKey) {
if (PmdConstants.XPATH_CLASS.equals(ref)) {
ref = null;
PmdProperty xpathMessage = getProperty(PmdConstants.XPATH_MESSAGE_PARAM);
if (xpathMessage == null) {
throw new IllegalArgumentException("Property '" + PmdConstants.XPATH_MESSAGE_PARAM + "' should be set for PMD rule " + sonarRuleKey);
}

message = xpathMessage.getValue();
removeProperty(PmdConstants.XPATH_MESSAGE_PARAM);
PmdProperty xpathExp = getProperty(PmdConstants.XPATH_EXPRESSION_PARAM);

if (xpathExp == null) {
throw new IllegalArgumentException("Property '" + PmdConstants.XPATH_EXPRESSION_PARAM + "' should be set for PMD rule " + sonarRuleKey);
}

xpathExp.setCdataValue(xpathExp.getValue());
clazz = PmdConstants.XPATH_CLASS;
language = PmdConstants.LANGUAGE_KEY;
name = sonarRuleKey;
}
}
}
Loading

0 comments on commit 655d590

Please sign in to comment.