Переглянути джерело

API: apply the same pattern between rules and profiles API. The extension point to define rules is org.sonar.api.rules.RuleRepository. The classes AnnotationRuleParser and XMLRuleParser are components that can be used but not extended.

tags/2.6
simonbrandhof 13 роки тому
джерело
коміт
fc24fe199e

+ 5
- 3
plugins/sonar-checkstyle-plugin/src/main/java/org/sonar/plugins/checkstyle/CheckstyleRuleRepository.java Переглянути файл

@@ -33,19 +33,21 @@ public final class CheckstyleRuleRepository extends RuleRepository {

// for user extensions
private ServerFileSystem fileSystem;
private XMLRuleParser xmlRuleParser;

public CheckstyleRuleRepository(ServerFileSystem fileSystem) {
public CheckstyleRuleRepository(ServerFileSystem fileSystem, XMLRuleParser xmlRuleParser) {
super(CheckstyleConstants.REPOSITORY_KEY, Java.KEY);
setName(CheckstyleConstants.REPOSITORY_NAME);
this.fileSystem = fileSystem;
this.xmlRuleParser = xmlRuleParser;
}

@Override
public List<Rule> createRules() {
List<Rule> rules = new ArrayList<Rule>();
rules.addAll(XMLRuleParser.parseXML(getClass().getResourceAsStream("/org/sonar/plugins/checkstyle/rules.xml")));
rules.addAll(xmlRuleParser.parse(getClass().getResourceAsStream("/org/sonar/plugins/checkstyle/rules.xml")));
for (File userExtensionXml : fileSystem.getExtensions(CheckstyleConstants.REPOSITORY_KEY, "xml")) {
rules.addAll(XMLRuleParser.parseXML(userExtensionXml));
rules.addAll(xmlRuleParser.parse(userExtensionXml));
}
return rules;
}

+ 2
- 1
plugins/sonar-checkstyle-plugin/src/test/java/org/sonar/plugins/checkstyle/CheckstyleRuleRepositoryTest.java Переглянути файл

@@ -22,6 +22,7 @@ package org.sonar.plugins.checkstyle;
import org.junit.Test;
import org.sonar.api.platform.ServerFileSystem;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.XMLRuleParser;

import java.util.List;

@@ -34,7 +35,7 @@ public class CheckstyleRuleRepositoryTest {
@Test
public void loadRepositoryFromXml() {
ServerFileSystem fileSystem = mock(ServerFileSystem.class);
CheckstyleRuleRepository repository = new CheckstyleRuleRepository(fileSystem);
CheckstyleRuleRepository repository = new CheckstyleRuleRepository(fileSystem, new XMLRuleParser());
List<Rule> rules = repository.createRules();
assertThat(rules.size(), greaterThan(100));
}

+ 5
- 2
plugins/sonar-findbugs-plugin/src/main/java/org/sonar/plugins/findbugs/FindbugsRuleRepository.java Переглянути файл

@@ -28,13 +28,16 @@ import java.util.List;

public final class FindbugsRuleRepository extends RuleRepository {

public FindbugsRuleRepository() {
private XMLRuleParser xmlRuleParser;

public FindbugsRuleRepository(XMLRuleParser xmlRuleParser) {
super(FindbugsConstants.REPOSITORY_KEY, Java.KEY);
setName(FindbugsConstants.REPOSITORY_NAME);
this.xmlRuleParser = xmlRuleParser;
}

@Override
public List<Rule> createRules() {
return XMLRuleParser.parseXML(getClass().getResourceAsStream("/org/sonar/plugins/findbugs/rules.xml"));
return xmlRuleParser.parse(getClass().getResourceAsStream("/org/sonar/plugins/findbugs/rules.xml"));
}
}

+ 2
- 1
plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsRuleFinder.java Переглянути файл

@@ -25,13 +25,14 @@ import java.util.List;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.rules.RuleQuery;
import org.sonar.api.rules.XMLRuleParser;

public class FindbugsRuleFinder implements RuleFinder {

private final List<Rule> findbugsRules;

public FindbugsRuleFinder() {
FindbugsRuleRepository repo = new FindbugsRuleRepository();
FindbugsRuleRepository repo = new FindbugsRuleRepository(new XMLRuleParser());
findbugsRules = repo.createRules();
for(Rule rule : findbugsRules){
rule.setRepositoryKey(FindbugsConstants.REPOSITORY_KEY);

+ 2
- 1
plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsRuleRepositoryTest.java Переглянути файл

@@ -27,12 +27,13 @@ import java.util.List;

import org.junit.Test;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.XMLRuleParser;

public class FindbugsRuleRepositoryTest {

@Test
public void testLoadRepositoryFromXml() {
FindbugsRuleRepository repository = new FindbugsRuleRepository();
FindbugsRuleRepository repository = new FindbugsRuleRepository(new XMLRuleParser());
List<Rule> rules = repository.createRules();
assertThat(rules.size(), greaterThan(300));
for (Rule rule : rules) {

+ 2
- 6
plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsTests.java Переглянути файл

@@ -35,11 +35,7 @@ import org.mockito.stubbing.Answer;
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.Rule;
import org.sonar.api.rules.RulePriority;
import org.sonar.api.rules.RuleQuery;
import org.sonar.api.rules.RulesManager;
import org.sonar.api.rules.*;
import org.sonar.test.TestUtils;
import org.xml.sax.SAXException;
@@ -93,7 +89,7 @@ public abstract class FindbugsTests {
RulesProfile profile = RulesProfile.create();
profile.setName(RulesProfile.SONAR_WAY_FINDBUGS_NAME);
profile.setLanguage(Java.KEY);
for (Rule rule : new FindbugsRuleRepository().createRules()) {
for (Rule rule : new FindbugsRuleRepository(new XMLRuleParser()).createRules()) {
rule.setRepositoryKey(FindbugsConstants.REPOSITORY_KEY);
profile.activateRule(rule, null);
}

+ 7
- 5
plugins/sonar-pmd-plugin/src/main/java/org/sonar/plugins/pmd/PmdRuleRepository.java Переглянути файл

@@ -19,6 +19,7 @@
*/
package org.sonar.plugins.pmd;

import com.google.common.collect.Lists;
import org.sonar.api.platform.ServerFileSystem;
import org.sonar.api.resources.Java;
import org.sonar.api.rules.Rule;
@@ -26,26 +27,27 @@ import org.sonar.api.rules.RuleRepository;
import org.sonar.api.rules.XMLRuleParser;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public final class PmdRuleRepository extends RuleRepository {

// for user extensions
private ServerFileSystem fileSystem;
private XMLRuleParser xmlRuleParser;

public PmdRuleRepository(ServerFileSystem fileSystem) {
public PmdRuleRepository(ServerFileSystem fileSystem, XMLRuleParser xmlRuleParser) {
super(PmdConstants.REPOSITORY_KEY, Java.KEY);
setName(PmdConstants.REPOSITORY_NAME);
this.fileSystem = fileSystem;
this.xmlRuleParser = xmlRuleParser;
}

@Override
public List<Rule> createRules() {
List<Rule> rules = new ArrayList<Rule>();
rules.addAll(XMLRuleParser.parseXML(getClass().getResourceAsStream("/org/sonar/plugins/pmd/rules.xml")));
List<Rule> rules = Lists.newArrayList();
rules.addAll(xmlRuleParser.parse(getClass().getResourceAsStream("/org/sonar/plugins/pmd/rules.xml")));
for (File userExtensionXml : fileSystem.getExtensions(PmdConstants.REPOSITORY_KEY, "xml")) {
rules.addAll(XMLRuleParser.parseXML(userExtensionXml));
rules.addAll(xmlRuleParser.parse(userExtensionXml));
}
return rules;
}

+ 2
- 5
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java Переглянути файл

@@ -17,10 +17,7 @@ import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.sonar.api.platform.ServerFileSystem;
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.RuleQuery;
import org.sonar.api.rules.*;
import org.sonar.api.utils.ValidationMessages;
import org.sonar.plugins.pmd.xml.PmdProperty;
import org.sonar.plugins.pmd.xml.PmdRule;
@@ -34,7 +31,7 @@ public class PmdProfileExporterTest {
@Test
public void testExportProfile() throws IOException, SAXException {
ServerFileSystem fileSystem = mock(ServerFileSystem.class);
PmdRuleRepository repository = new PmdRuleRepository(fileSystem);
PmdRuleRepository repository = new PmdRuleRepository(fileSystem, new XMLRuleParser());
List<Rule> rules = repository.createRules();

RuleFinder ruleFinder = new PmdRuleFinder(rules);

+ 2
- 1
plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdRuleRepositoryTest.java Переглянути файл

@@ -28,13 +28,14 @@ import java.util.List;
import org.junit.Test;
import org.sonar.api.platform.ServerFileSystem;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.XMLRuleParser;

public class PmdRuleRepositoryTest {

@Test
public void testLoadRepositoryFromXml() {
ServerFileSystem fileSystem = mock(ServerFileSystem.class);
PmdRuleRepository repository = new PmdRuleRepository(fileSystem);
PmdRuleRepository repository = new PmdRuleRepository(fileSystem, new XMLRuleParser());
List<Rule> rules = repository.createRules();
assertThat(rules.size(), greaterThan(100));
}

sonar-plugin-api/src/main/java/org/sonar/api/rules/AnnotationRuleRepository.java → sonar-plugin-api/src/main/java/org/sonar/api/rules/AnnotationRuleParser.java Переглянути файл

@@ -23,6 +23,7 @@ import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.ServerComponent;
import org.sonar.api.utils.AnnotationUtils;
import org.sonar.check.Check;

@@ -33,50 +34,34 @@ import java.util.List;
/**
* @since 2.3
*/
public final class AnnotationRuleRepository extends RuleRepository {
public final class AnnotationRuleParser implements ServerComponent {

private static final Logger LOG = LoggerFactory.getLogger(AnnotationRuleRepository.class);
private static final Logger LOG = LoggerFactory.getLogger(AnnotationRuleParser.class);

private Collection<Class> annotatedClasses;

/**
* Use the factory method create()
*/
private AnnotationRuleRepository(String key, String language, String name, Collection<Class> annotatedClasses) {
super(key, language);
setName(name);
this.annotatedClasses = annotatedClasses;
}

public static AnnotationRuleRepository create(String key, String language, String name, Collection<Class> annotatedClasses) {
return new AnnotationRuleRepository(key, language, name, annotatedClasses);
}

@Override
public List<Rule> createRules() {
public List<Rule> parse(String repositoryKey, Collection<Class> annotatedClasses) {
List<Rule> rules = Lists.newArrayList();
for (Class annotatedClass : annotatedClasses) {
rules.add(create(annotatedClass));
rules.add(create(repositoryKey, annotatedClass));
}
return rules;
}

private Rule create(Class annotatedClass) {
private Rule create(String repositoryKey, Class annotatedClass) {
org.sonar.check.Rule ruleAnnotation = AnnotationUtils.getClassAnnotation(annotatedClass, org.sonar.check.Rule.class);
if (ruleAnnotation != null) {
return toRule(annotatedClass, ruleAnnotation);
return toRule(repositoryKey, annotatedClass, ruleAnnotation);
}
Check checkAnnotation = AnnotationUtils.getClassAnnotation(annotatedClass, Check.class);
if (checkAnnotation != null) {
return toRule(annotatedClass, checkAnnotation);
return toRule(repositoryKey, annotatedClass, checkAnnotation);
}
LOG.warn("The class " + annotatedClass.getCanonicalName() + " is not a check template. It should be annotated with " + Rule.class);
LOG.warn("The class " + annotatedClass.getCanonicalName() + " should be annotated with " + Rule.class);
return null;
}

private Rule toRule(Class clazz, org.sonar.check.Rule ruleAnnotation) {
String key = StringUtils.defaultIfEmpty(ruleAnnotation.key(), clazz.getCanonicalName());
Rule rule = Rule.create(getKey(), key, ruleAnnotation.name());
private Rule toRule(String repositoryKey, Class clazz, org.sonar.check.Rule ruleAnnotation) {
String ruleKey = StringUtils.defaultIfEmpty(ruleAnnotation.key(), clazz.getCanonicalName());
Rule rule = Rule.create(repositoryKey, ruleKey, ruleAnnotation.name());
rule.setDescription(ruleAnnotation.description());
rule.setRulesCategory(RulesCategory.fromIsoCategory(ruleAnnotation.isoCategory()));
rule.setPriority(RulePriority.fromCheckPriority(ruleAnnotation.priority()));
@@ -91,9 +76,9 @@ public final class AnnotationRuleRepository extends RuleRepository {
return rule;
}

private Rule toRule(Class clazz, Check checkAnnotation) {
String key = StringUtils.defaultIfEmpty(checkAnnotation.key(), clazz.getCanonicalName());
Rule rule = Rule.create(getKey(), key, checkAnnotation.title());
private Rule toRule(String repositoryKey, Class clazz, Check checkAnnotation) {
String ruleKey = StringUtils.defaultIfEmpty(checkAnnotation.key(), clazz.getCanonicalName());
Rule rule = Rule.create(repositoryKey, ruleKey, checkAnnotation.title());
rule.setDescription(checkAnnotation.description());
rule.setRulesCategory(RulesCategory.fromIsoCategory(checkAnnotation.isoCategory()));
rule.setPriority(RulePriority.fromCheckPriority(checkAnnotation.priority()));

+ 7
- 10
sonar-plugin-api/src/main/java/org/sonar/api/rules/XMLRuleParser.java Переглянути файл

@@ -27,6 +27,7 @@ import org.codehaus.stax2.XMLInputFactory2;
import org.codehaus.staxmate.SMInputFactory;
import org.codehaus.staxmate.in.SMHierarchicCursor;
import org.codehaus.staxmate.in.SMInputCursor;
import org.sonar.api.ServerComponent;
import org.sonar.api.utils.SonarException;

import javax.xml.stream.XMLInputFactory;
@@ -38,17 +39,13 @@ import java.util.List;
/**
* @since 2.3
*/
public final class XMLRuleParser {
public final class XMLRuleParser implements ServerComponent {

private XMLRuleParser() {
// only static methods
}

public static List<Rule> parseXML(File file) {
public List<Rule> parse(File file) {
Reader reader = null;
try {
reader = new InputStreamReader(FileUtils.openInputStream(file), CharEncoding.UTF_8);
return parseXML(reader);
return parse(reader);

} catch (IOException e) {
throw new SonarException("Fail to load the file: " + file, e);
@@ -61,11 +58,11 @@ public final class XMLRuleParser {
/**
* Warning : the input stream is closed in this method
*/
public static List<Rule> parseXML(InputStream input) {
public List<Rule> parse(InputStream input) {
Reader reader = null;
try {
reader = new InputStreamReader(input, CharEncoding.UTF_8);
return parseXML(reader);
return parse(reader);

} catch (IOException e) {
throw new SonarException("Fail to load the xml stream", e);
@@ -75,7 +72,7 @@ public final class XMLRuleParser {
}
}

public static List<Rule> parseXML(Reader reader) {
public List<Rule> parse(Reader reader) {
XMLInputFactory xmlFactory = XMLInputFactory2.newInstance();
xmlFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
xmlFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE);

+ 5
- 5
sonar-plugin-api/src/test/java/org/sonar/api/rules/XMLRuleParserTest.java Переглянути файл

@@ -35,7 +35,7 @@ public class XMLRuleParserTest {

@Test
public void parseXml() {
List<Rule> rules = XMLRuleParser.parseXML(getClass().getResourceAsStream("/org/sonar/api/rules/XMLRuleParserTest/rules.xml"));
List<Rule> rules = new XMLRuleParser().parse(getClass().getResourceAsStream("/org/sonar/api/rules/XMLRuleParserTest/rules.xml"));
assertThat(rules.size(), is(2));

Rule rule = rules.get(0);
@@ -59,17 +59,17 @@ public class XMLRuleParserTest {

@Test(expected = SonarException.class)
public void failIfMissingRuleKey() {
XMLRuleParser.parseXML(new StringReader("<rules><rule><name>Foo</name></rule></rules>"));
new XMLRuleParser().parse(new StringReader("<rules><rule><name>Foo</name></rule></rules>"));
}

@Test(expected = SonarException.class)
public void failIfMissingPropertyKey() {
XMLRuleParser.parseXML(new StringReader("<rules><rule><key>foo</key><name>Foo</name><param></param></rule></rules>"));
new XMLRuleParser().parse(new StringReader("<rules><rule><key>foo</key><name>Foo</name><param></param></rule></rules>"));
}

@Test
public void utf8Encoding() {
List<Rule> rules = XMLRuleParser.parseXML(getClass().getResourceAsStream("/org/sonar/api/rules/XMLRuleParserTest/utf8.xml"));
List<Rule> rules = new XMLRuleParser().parse(getClass().getResourceAsStream("/org/sonar/api/rules/XMLRuleParserTest/utf8.xml"));
assertThat(rules.size(), is(1));
Rule rule = rules.get(0);
assertThat(rule.getKey(), is("com.puppycrawl.tools.checkstyle.checks.naming.LocalVariableNameCheck"));
@@ -82,7 +82,7 @@ public class XMLRuleParserTest {
@Test
public void supportDeprecatedFormat() {
// the deprecated format uses some attributes instead of nodes
List<Rule> rules = XMLRuleParser.parseXML(getClass().getResourceAsStream("/org/sonar/api/rules/XMLRuleParserTest/deprecated.xml"));
List<Rule> rules = new XMLRuleParser().parse(getClass().getResourceAsStream("/org/sonar/api/rules/XMLRuleParserTest/deprecated.xml"));
assertThat(rules.size(), is(1));
Rule rule = rules.get(0);
assertThat(rule.getPriority(), Is.is(RulePriority.CRITICAL));

+ 2
- 0
sonar-server/src/main/java/org/sonar/server/platform/Platform.java Переглянути файл

@@ -33,6 +33,7 @@ import org.sonar.api.profiles.XMLProfileParser;
import org.sonar.api.profiles.XMLProfileSerializer;
import org.sonar.api.resources.Languages;
import org.sonar.api.rules.DefaultRulesManager;
import org.sonar.api.rules.XMLRuleParser;
import org.sonar.api.utils.HttpDownloader;
import org.sonar.api.utils.IocContainer;
import org.sonar.api.utils.TimeProfiler;
@@ -175,6 +176,7 @@ public final class Platform {
servicesContainer.as(Characteristics.CACHE).addComponent(AnnotationProfileParser.class);
servicesContainer.as(Characteristics.CACHE).addComponent(XMLProfileParser.class);
servicesContainer.as(Characteristics.CACHE).addComponent(XMLProfileSerializer.class);
servicesContainer.as(Characteristics.CACHE).addComponent(XMLRuleParser.class);
servicesContainer.as(Characteristics.CACHE).addComponent(DefaultRuleFinder.class);
servicesContainer.as(Characteristics.CACHE).addComponent(DeprecatedRuleRepositories.class);
servicesContainer.as(Characteristics.CACHE).addComponent(DeprecatedProfiles.class);

Завантаження…
Відмінити
Зберегти