From ee7485223662fe16f1e4be83cbd633e81526d04d Mon Sep 17 00:00:00 2001
From: Stefan CORDES <50696194+ca-stefan-cordes@users.noreply.github.com>
Date: Thu, 3 Dec 2020 17:40:24 +0100
Subject: [PATCH] LineNumbers displaying on Issue #15
---
pom.xml | 5 ++
.../sonarqube/rule/MuleRulesDefinition.java | 8 ++++
.../rule/scope/ApplicationStrategyScope.java | 2 +-
.../rule/scope/FileStrategyScope.java | 47 ++++++++++++++++++-
.../rule/scope/SonarXmlCheckHelper.java | 19 ++++++++
.../services/tools/validation/rules/Rule.java | 16 +++++++
src/main/resources/mule3.properties | 1 +
src/main/resources/mule4.properties | 1 +
src/test/resources/rules-3.xml | 6 ++-
src/test/resources/rules-4.xml | 6 ++-
10 files changed, 105 insertions(+), 6 deletions(-)
create mode 100644 src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/SonarXmlCheckHelper.java
diff --git a/pom.xml b/pom.xml
index e620c8b..3fb1e1e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -36,6 +36,11 @@
provided
+
+ org.sonarsource.analyzer-commons
+ sonar-xml-parsing
+ 1.12.0.632
+
org.jdom
jdom2
diff --git a/src/main/java/com/mulesoft/services/tools/sonarqube/rule/MuleRulesDefinition.java b/src/main/java/com/mulesoft/services/tools/sonarqube/rule/MuleRulesDefinition.java
index c38c34a..33b8ef5 100644
--- a/src/main/java/com/mulesoft/services/tools/sonarqube/rule/MuleRulesDefinition.java
+++ b/src/main/java/com/mulesoft/services/tools/sonarqube/rule/MuleRulesDefinition.java
@@ -36,6 +36,7 @@ public interface PARAMS {
String CATEGORY = "category";
String SCOPE = "scope";
String XPATH = "xpath-expression";
+ String XPATH_LOCATION_HINT = "xpath-location-hint";
}
@Override
@@ -97,8 +98,13 @@ private void addRuleTemplate(NewRepository repository, String language) {
.setType(RuleParamType.STRING);
x1Rule.createParam(PARAMS.XPATH).setDescription(prop.getProperty("rule.template.parameter.xpath"))
.setType(RuleParamType.STRING);
+ x1Rule.createParam(PARAMS.XPATH_LOCATION_HINT).setDescription(prop.getProperty("rule.template.parameter.xpathlocationhint"))
+ .setType(RuleParamType.STRING);
x1Rule.createParam(PARAMS.SCOPE).setDescription(prop.getProperty("rule.template.parameter.scope"))
.setType(RuleParamType.STRING);
+
+ logger.info("addRuleTemplate x1Rule="+x1Rule);
+
}
private void addRule(NewRepository repository, Ruleset ruleset,
@@ -113,6 +119,8 @@ private void addRule(NewRepository repository, Ruleset ruleset,
x1Rule.addTags(language);
x1Rule.createParam(PARAMS.CATEGORY).setDefaultValue(ruleset.getCategory()).setType(RuleParamType.STRING);
x1Rule.createParam(PARAMS.XPATH).setDefaultValue(rule.getValue()).setType(RuleParamType.STRING);
+ logger.info("LocationHint="+rule.getLocationHint()+" for "+rule.getName());
+ x1Rule.createParam(PARAMS.XPATH_LOCATION_HINT).setDefaultValue(rule.getLocationHint()).setType(RuleParamType.STRING);
if (rule.getApplies() != null) {
x1Rule.createParam(PARAMS.SCOPE).setDefaultValue(rule.getApplies()).setType(RuleParamType.STRING);
}
diff --git a/src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/ApplicationStrategyScope.java b/src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/ApplicationStrategyScope.java
index 86f4645..2b9e7da 100644
--- a/src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/ApplicationStrategyScope.java
+++ b/src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/ApplicationStrategyScope.java
@@ -37,7 +37,7 @@ public void validate(XPathProcessor xpathValidator, Map>
String ruleId = rule.ruleKey().toString();
boolean valid = xpathValidator.processXPath(rule.param(MuleRulesDefinition.PARAMS.XPATH).trim(),
rootElement, Boolean.class).booleanValue();
- logger.info("Validation Result: " + valid + " : File: " + t.filename() + " :Rule:" + rule.ruleKey());
+ logger.info("Validation Result: " + valid + " : File: " + t.filename() + " :Rule:" + rule.ruleKey()+" internalKey="+rule.internalKey());
if (!valid && !valids.contains(ruleId) && !issues.containsKey(rule.ruleKey())) {
NewIssue newIssue = context.newIssue().forRule(rule.ruleKey());
NewIssueLocation primaryLocation = newIssue.newLocation().on(t);
diff --git a/src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/FileStrategyScope.java b/src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/FileStrategyScope.java
index 89428ac..2642c45 100644
--- a/src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/FileStrategyScope.java
+++ b/src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/FileStrategyScope.java
@@ -9,6 +9,11 @@
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
+
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.rule.ActiveRule;
import org.sonar.api.batch.sensor.SensorContext;
@@ -18,6 +23,10 @@
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
+import org.sonarsource.analyzer.commons.xml.XmlFile;
+import org.sonarsource.analyzer.commons.xml.XmlTextRange;
+import org.w3c.dom.Node;
+
import com.mulesoft.services.tools.sonarqube.rule.MuleRulesDefinition;
import com.mulesoft.services.xpath.XPathProcessor;
@@ -35,8 +44,44 @@ public void validate(XPathProcessor xpathValidator, Map>
rootElement, Boolean.class).booleanValue();
logger.info("Validation Result: " + valid + " : File: " + t.filename() + " :Rule:" + rule.ruleKey());
if (!valid) {
+
+ XmlTextRange textRange;
+ try {
+ // see org.sonarsource.analyzer.commons.xml.checks.SonarXmlCheck.reportIssue(Node, String)
+ SonarXmlCheckHelper tempSonarXmlCheckHelper = new SonarXmlCheckHelper();
+ XmlFile xmlFile = XmlFile.create(t);
+ tempSonarXmlCheckHelper.scanFile(context, rule.ruleKey(), xmlFile); // just to fill the properties
+ String locationFindingXPath = rule.param(MuleRulesDefinition.PARAMS.XPATH_LOCATION_HINT).trim();
+ if (locationFindingXPath == null || locationFindingXPath.length()==0) {
+ logger.info("No locationFindingXPath:params="+rule.params());
+ textRange = null;
+ } else {
+ Node locationElement = (Node)XPathFactory.newInstance().newXPath().compile(locationFindingXPath).evaluate(xmlFile.getDocument().getFirstChild(), XPathConstants.NODE);
+ if (locationElement == null) {
+ textRange= null;
+ logger.warn("Did not find node for "+locationFindingXPath);
+ } else {
+ textRange = XmlFile.nodeLocation(locationElement);
+ logger.info("Found textRange="+textRange);
+ }
+ }
+ } catch (RuntimeException | XPathExpressionException e) {
+ logger.error("Ignore",e);
+ textRange= null;
+ }
+
NewIssue newIssue = context.newIssue().forRule(rule.ruleKey());
- NewIssueLocation primaryLocation = newIssue.newLocation().on(t);
+ NewIssueLocation primaryLocation;
+ if (textRange == null) {
+ primaryLocation = newIssue.newLocation().on(t);
+ } else {
+ primaryLocation = newIssue.newLocation().on(t) .at(t.newRange(
+ textRange.getStartLine(),
+ textRange.getStartColumn(),
+ textRange.getEndLine(),
+ textRange.getEndColumn()));
+ }
+
newIssue.at(primaryLocation);
addIssue(issues, rule, newIssue);
}
diff --git a/src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/SonarXmlCheckHelper.java b/src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/SonarXmlCheckHelper.java
new file mode 100644
index 0000000..92e0d4f
--- /dev/null
+++ b/src/main/java/com/mulesoft/services/tools/sonarqube/rule/scope/SonarXmlCheckHelper.java
@@ -0,0 +1,19 @@
+package com.mulesoft.services.tools.sonarqube.rule.scope;
+
+import org.sonarsource.analyzer.commons.xml.XmlFile;
+import org.sonarsource.analyzer.commons.xml.checks.SonarXmlCheck;
+
+/**
+ *
+ */
+public class SonarXmlCheckHelper extends SonarXmlCheck {
+
+ /**
+ *
+ */
+ @Override
+ public void scanFile(XmlFile aFile) {
+ // nothing to do
+ }
+
+}
diff --git a/src/main/java/com/mulesoft/services/tools/validation/rules/Rule.java b/src/main/java/com/mulesoft/services/tools/validation/rules/Rule.java
index 100b7f0..e76c8b0 100644
--- a/src/main/java/com/mulesoft/services/tools/validation/rules/Rule.java
+++ b/src/main/java/com/mulesoft/services/tools/validation/rules/Rule.java
@@ -99,6 +99,8 @@ public class Rule {
protected String applies;
@XmlAttribute(name = "type")
protected String type;
+ @XmlAttribute(name = "locationHint")
+ private String locationHint;
/**
* Gets the value of the value property.
@@ -269,4 +271,18 @@ public void setType(String value) {
this.type = value;
}
+ /**
+ *
+ */
+ public String getLocationHint() {
+ return locationHint;
+ }
+
+ /**
+ * @see #locationHint
+ */
+ public void setLocationHint(String aLocationHint) {
+ locationHint = aLocationHint;
+ }
+
}
diff --git a/src/main/resources/mule3.properties b/src/main/resources/mule3.properties
index cfe0014..41ef58b 100644
--- a/src/main/resources/mule3.properties
+++ b/src/main/resources/mule3.properties
@@ -19,6 +19,7 @@ rule.template.name=Track issues on Mule 3
rule.template.description=Rule Template for mule 3
rule.template.parameter.scope=The scope of the rules. It should either file or application
rule.template.parameter.xpath=XPath expression to be evaluated
+rule.template.parameter.xpathlocationhint=XPath expression to find the node
rule.template.parameter.category=Category of the rule
diff --git a/src/main/resources/mule4.properties b/src/main/resources/mule4.properties
index a5b3247..1546441 100644
--- a/src/main/resources/mule4.properties
+++ b/src/main/resources/mule4.properties
@@ -19,6 +19,7 @@ rule.template.name=Track issues on Mule 4
rule.template.description=Rule Template for mule 4
rule.template.parameter.scope=The scope of the rules. It should either file or application
rule.template.parameter.xpath=XPath expression to be evaluated
+rule.template.parameter.xpathlocationhint=XPath expression to find the node
rule.template.parameter.category=Category of the rule
diff --git a/src/test/resources/rules-3.xml b/src/test/resources/rules-3.xml
index 8c7ae73..90e4619 100644
--- a/src/test/resources/rules-3.xml
+++ b/src/test/resources/rules-3.xml
@@ -140,7 +140,8 @@
+ severity="MAJOR" type="vulnerability"
+ locationHint="//*[local-name()='listener-config']">
count(//mule:mule/http:listener-config)=0
or
//mule:mule/http:listener-config/@protocol='HTTPS'
@@ -148,7 +149,8 @@
+ severity="MAJOR" type="code_smell"
+ locationHint="//*[local-name()='listener-config']">
count(//mule:mule/http:listener-config)=0
or
//mule:mule/http:listener-config/@port='${https.port}' or
diff --git a/src/test/resources/rules-4.xml b/src/test/resources/rules-4.xml
index 75bc092..6b8f02e 100644
--- a/src/test/resources/rules-4.xml
+++ b/src/test/resources/rules-4.xml
@@ -97,7 +97,8 @@
+ severity="MAJOR" type="vulnerability"
+ locationHint="//*[local-name()='listener-config']">
count(//mule:mule/http:listener-config)=0
or
//mule:mule/http:listener-config/http:listener-connection/@protocol='HTTPS'
@@ -105,7 +106,8 @@
+ severity="MAJOR" type="code_smell"
+ locationHint="//*[local-name()='listener-config']">
count(//mule:mule/http:listener-config)=0
or
//mule:mule/http:listener-config/http:listener-connection/@port='${https.port}'