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}'