@@ -19,14 +19,20 @@ | |||
*/ | |||
package org.sonar.plugins.checkstyle; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.profiles.XMLProfileDefinition; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.profiles.XMLProfileParser; | |||
import org.sonar.api.utils.ValidationMessages; | |||
public final class SonarWayProfile extends XMLProfileDefinition { | |||
public final class SonarWayProfile extends ProfileDefinition { | |||
public SonarWayProfile(RuleFinder ruleFinder) { | |||
super(SunConventionsProfile.class.getClassLoader(), "org/sonar/plugins/checkstyle/profile-sonar-way.xml", ruleFinder); | |||
private XMLProfileParser xmlProfileParser; | |||
public SonarWayProfile(XMLProfileParser xmlProfileParser) { | |||
this.xmlProfileParser = xmlProfileParser; | |||
} | |||
public RulesProfile createProfile(ValidationMessages messages) { | |||
return xmlProfileParser.parseResource(getClass().getClassLoader(), "org/sonar/plugins/checkstyle/profile-sonar-way.xml", messages); | |||
} | |||
} |
@@ -21,9 +21,6 @@ package org.sonar.plugins.checkstyle; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.profiles.XMLProfileDefinition; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.utils.ValidationMessages; | |||
public class SonarWayWithFindbugsProfile extends ProfileDefinition { |
@@ -19,14 +19,22 @@ | |||
*/ | |||
package org.sonar.plugins.checkstyle; | |||
import org.sonar.api.profiles.ProfileDefinition; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.profiles.XMLProfileDefinition; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.profiles.XMLProfileParser; | |||
import org.sonar.api.utils.ValidationMessages; | |||
public final class SunConventionsProfile extends XMLProfileDefinition { | |||
public final class SunConventionsProfile extends ProfileDefinition { | |||
public SunConventionsProfile(RuleFinder ruleFinder) { | |||
super(SunConventionsProfile.class.getClassLoader(), "org/sonar/plugins/checkstyle/profile-sun-conventions.xml", ruleFinder); | |||
private XMLProfileParser xmlProfileParser; | |||
public SunConventionsProfile(XMLProfileParser xmlProfileParser) { | |||
this.xmlProfileParser = xmlProfileParser; | |||
} | |||
public RulesProfile createProfile(ValidationMessages messages) { | |||
return xmlProfileParser.parseResource(getClass().getClassLoader(), "org/sonar/plugins/checkstyle/profile-sun-conventions.xml", messages); | |||
} | |||
} |
@@ -24,6 +24,7 @@ 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.profiles.XMLProfileParser; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.utils.ValidationMessages; | |||
@@ -38,8 +39,8 @@ import static org.mockito.Mockito.when; | |||
public class SonarWayProfileTest { | |||
@Test | |||
public void create() { | |||
ProfileDefinition sonarWay = new SonarWayProfile(newRuleFinder()); | |||
public void shouldCreateProfile() { | |||
ProfileDefinition sonarWay = new SonarWayProfile(new XMLProfileParser(newRuleFinder())); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RulesProfile profile = sonarWay.createProfile(validation); | |||
assertThat(profile.getActiveRulesByRepository(CheckstyleConstants.REPOSITORY_KEY).size(), greaterThan(1)); |
@@ -23,11 +23,12 @@ import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.profiles.RulesProfile; | |||
import org.sonar.api.profiles.XMLProfileParser; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import static org.hamcrest.core.Is.is; | |||
import static org.hamcrest.core.Is.is; | |||
import static org.junit.Assert.assertThat; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
@@ -36,9 +37,9 @@ import static org.mockito.Mockito.when; | |||
public class SonarWayWithFindbugsProfileTest { | |||
@Test | |||
public void sameAsSonarWay() { | |||
public void shouldBeSameAsSonarWay() { | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
SonarWayProfile sonarWay = new SonarWayProfile(ruleFinder); | |||
SonarWayProfile sonarWay = new SonarWayProfile(new XMLProfileParser(ruleFinder)); | |||
RulesProfile withoutFindbugs = sonarWay.createProfile(ValidationMessages.create()); | |||
RulesProfile withFindbugs = new SonarWayWithFindbugsProfile(sonarWay).createProfile(ValidationMessages.create()); | |||
assertThat(withFindbugs.getActiveRules().size(), is(withoutFindbugs.getActiveRules().size())); |
@@ -25,6 +25,7 @@ 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.profiles.XMLProfileParser; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.utils.ValidationMessages; | |||
@@ -37,8 +38,8 @@ import static org.mockito.Mockito.when; | |||
public class SunConventionsProfileTest { | |||
@Test | |||
public void create() { | |||
ProfileDefinition definition = new SunConventionsProfile(newRuleFinder()); | |||
public void shouldCreateProfile() { | |||
ProfileDefinition definition = new SunConventionsProfile(new XMLProfileParser(newRuleFinder())); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RulesProfile sunProfile = definition.createProfile(validation); | |||
assertThat(sunProfile.getActiveRulesByRepository(CheckstyleConstants.REPOSITORY_KEY).size(), greaterThan(1)); |
@@ -19,15 +19,13 @@ | |||
*/ | |||
package org.sonar.plugins.findbugs; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import org.sonar.api.platform.ServerFileSystem; | |||
import org.sonar.api.resources.Java; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleRepository; | |||
import org.sonar.api.rules.XMLRuleParser; | |||
import java.util.List; | |||
public final class FindbugsRuleRepository extends RuleRepository { | |||
public FindbugsRuleRepository() { | |||
@@ -37,8 +35,6 @@ public final class FindbugsRuleRepository extends RuleRepository { | |||
@Override | |||
public List<Rule> createRules() { | |||
List<Rule> rules = new ArrayList<Rule>(); | |||
rules.addAll(XMLRuleParser.parseXML(getClass().getResourceAsStream("/org/sonar/plugins/findbugs/rules.xml"))); | |||
return rules; | |||
return XMLRuleParser.parseXML(getClass().getResourceAsStream("/org/sonar/plugins/findbugs/rules.xml")); | |||
} | |||
} |
@@ -30,7 +30,7 @@ import org.sonar.api.utils.ValidationMessages; | |||
public class SonarWayWithFindbugsProfileTest { | |||
@Test | |||
public void create() { | |||
public void shouldCreateProfile() { | |||
FindbugsProfileImporter importer = new FindbugsProfileImporter(new FindbugsRuleFinder()); | |||
SonarWayWithFindbugsProfile sonarWayWithFindbugs = new SonarWayWithFindbugsProfile(importer); | |||
ValidationMessages validation = ValidationMessages.create(); |
@@ -40,7 +40,7 @@ import org.sonar.api.utils.ValidationMessages; | |||
public class SonarWayProfileTest { | |||
@Test | |||
public void create() { | |||
public void shouldCreateProfile() { | |||
ProfileDefinition sonarWay = new SonarWayProfile(createPmdProfileImporter()); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RulesProfile profile = sonarWay.createProfile(validation); |
@@ -39,7 +39,7 @@ import org.sonar.api.utils.ValidationMessages; | |||
public class SonarWayWithFindbugsProfileTest { | |||
@Test | |||
public void create() { | |||
public void shouldCreateProfile() { | |||
SonarWayWithFindbugsProfile sonarWayWithFindbugs = new SonarWayWithFindbugsProfile(new SonarWayProfile(createPmdProfileImporter())); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RulesProfile profile = sonarWayWithFindbugs.createProfile(validation); |
@@ -38,7 +38,7 @@ import org.sonar.api.utils.ValidationMessages; | |||
public class SunConventionsProfileTest { | |||
@Test | |||
public void create() { | |||
public void shouldCreateProfile() { | |||
SunConventionsProfile sunConvention = new SunConventionsProfile(createPmdProfileImporter()); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RulesProfile profile = sunConvention.createProfile(validation); |
@@ -19,6 +19,8 @@ | |||
*/ | |||
package org.sonar.api.profiles; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.ServerComponent; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleAnnotationUtils; | |||
import org.sonar.api.rules.RuleFinder; | |||
@@ -31,45 +33,34 @@ import java.util.Collection; | |||
/** | |||
* @since 2.3 | |||
*/ | |||
public abstract class AnnotationProfileDefinition extends ProfileDefinition { | |||
public final class AnnotationProfileParser implements ServerComponent { | |||
private String name; | |||
private String language; | |||
private String repositoryKey; | |||
private Collection<Class> annotatedClasses; | |||
private RuleFinder ruleFinder; | |||
protected AnnotationProfileDefinition(String repositoryKey, String profileName, String language, Collection<Class> annotatedClasses, RuleFinder ruleFinder) { | |||
this.name = profileName; | |||
this.language = language; | |||
this.repositoryKey = repositoryKey; | |||
this.annotatedClasses = annotatedClasses; | |||
public AnnotationProfileParser(RuleFinder ruleFinder) { | |||
this.ruleFinder = ruleFinder; | |||
} | |||
@Override | |||
public RulesProfile createProfile(ValidationMessages validation) { | |||
RulesProfile profile = RulesProfile.create(name, language); | |||
if (annotatedClasses != null) { | |||
for (Class aClass : annotatedClasses) { | |||
BelongsToProfile belongsToProfile = (BelongsToProfile) aClass.getAnnotation(BelongsToProfile.class); | |||
registerRule(aClass, belongsToProfile, profile, validation); | |||
} | |||
public RulesProfile parse(String repositoryKey, String profileName, String language, Collection<Class> annotatedClasses, ValidationMessages messages) { | |||
RulesProfile profile = RulesProfile.create(profileName, language); | |||
for (Class aClass : annotatedClasses) { | |||
BelongsToProfile belongsToProfile = (BelongsToProfile) aClass.getAnnotation(BelongsToProfile.class); | |||
addRule(aClass, belongsToProfile, profile, repositoryKey, messages); | |||
} | |||
return profile; | |||
} | |||
private void registerRule(Class aClass, BelongsToProfile belongsToProfile, RulesProfile profile, ValidationMessages validation) { | |||
if (belongsToProfile != null) { | |||
private void addRule(Class aClass, BelongsToProfile annotation, RulesProfile profile, String repositoryKey, ValidationMessages messages) { | |||
if (annotation != null && StringUtils.equals(annotation.title(), profile.getName())) { | |||
String ruleKey = RuleAnnotationUtils.getRuleKey(aClass); | |||
Rule rule = ruleFinder.findByKey(repositoryKey, ruleKey); | |||
if (rule == null) { | |||
validation.addErrorText("Rule not found: [repository=" + repositoryKey + ", key=" + ruleKey + "]"); | |||
messages.addWarningText("Rule not found: [repository=" + repositoryKey + ", key=" + ruleKey + "]"); | |||
} else { | |||
RulePriority priority = null; | |||
if (belongsToProfile.priority() != null) { | |||
priority = RulePriority.fromCheckPriority(belongsToProfile.priority()); | |||
if (annotation.priority() != null) { | |||
priority = RulePriority.fromCheckPriority(annotation.priority()); | |||
} | |||
profile.activateRule(rule, priority); | |||
} |
@@ -23,6 +23,9 @@ import org.sonar.api.ServerExtension; | |||
import org.sonar.api.utils.ValidationMessages; | |||
/** | |||
* Define a profile which is automatically registered during sonar startup. | |||
* The components <code>AnnotationProfileParser</code> and <code>XMLProfileParser</code> can be used to help implementing the method create(). | |||
* | |||
* @since 2.3 | |||
*/ | |||
public abstract class ProfileDefinition implements ServerExtension { |
@@ -1,58 +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.api.profiles; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.lang.CharEncoding; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.utils.SonarException; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import java.io.InputStreamReader; | |||
import java.io.Reader; | |||
import java.nio.charset.Charset; | |||
import java.util.List; | |||
/** | |||
* @since 2.3 | |||
*/ | |||
public abstract class XMLProfileDefinition extends ProfileDefinition { | |||
private RuleFinder ruleFinder; | |||
private ClassLoader classloader; | |||
private String xmlClassPath; | |||
protected XMLProfileDefinition(ClassLoader classloader, String xmlClassPath, RuleFinder ruleFinder) { | |||
this.ruleFinder = ruleFinder; | |||
this.classloader = classloader; | |||
this.xmlClassPath = xmlClassPath; | |||
} | |||
@Override | |||
public final RulesProfile createProfile(ValidationMessages validation) { | |||
Reader reader = new InputStreamReader(classloader.getResourceAsStream(xmlClassPath), Charset.forName(CharEncoding.UTF_8)); | |||
try { | |||
return XMLProfileImporter.create(ruleFinder).importProfile(reader, validation); | |||
} finally { | |||
IOUtils.closeQuietly(reader); | |||
} | |||
} | |||
} |
@@ -19,11 +19,14 @@ | |||
*/ | |||
package org.sonar.api.profiles; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.lang.CharEncoding; | |||
import org.apache.commons.lang.StringUtils; | |||
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.rules.ActiveRule; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
@@ -32,26 +35,34 @@ import org.sonar.api.utils.ValidationMessages; | |||
import javax.xml.stream.XMLInputFactory; | |||
import javax.xml.stream.XMLStreamException; | |||
import java.io.InputStreamReader; | |||
import java.io.Reader; | |||
import java.nio.charset.Charset; | |||
import java.util.HashMap; | |||
import java.util.Map; | |||
/** | |||
* @since 2.3 | |||
*/ | |||
public final class XMLProfileImporter { | |||
public final class XMLProfileParser implements ServerComponent { | |||
private RuleFinder ruleFinder; | |||
private XMLProfileImporter(RuleFinder ruleFinder) { | |||
public XMLProfileParser(RuleFinder ruleFinder) { | |||
this.ruleFinder = ruleFinder; | |||
} | |||
public static XMLProfileImporter create(RuleFinder ruleFinder) { | |||
return new XMLProfileImporter(ruleFinder); | |||
public RulesProfile parseResource(ClassLoader classloader, String xmlClassPath, ValidationMessages messages) { | |||
Reader reader = new InputStreamReader(classloader.getResourceAsStream(xmlClassPath), Charset.forName(CharEncoding.UTF_8)); | |||
try { | |||
return parse(reader, messages); | |||
} finally { | |||
IOUtils.closeQuietly(reader); | |||
} | |||
} | |||
public RulesProfile importProfile(Reader reader, ValidationMessages messages) { | |||
public RulesProfile parse(Reader reader, ValidationMessages messages) { | |||
RulesProfile profile = RulesProfile.create(); | |||
SMInputFactory inputFactory = initStax(); | |||
try { |
@@ -21,6 +21,7 @@ package org.sonar.api.profiles; | |||
import org.apache.commons.lang.StringEscapeUtils; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.ServerComponent; | |||
import org.sonar.api.rules.ActiveRule; | |||
import org.sonar.api.rules.ActiveRuleParam; | |||
import org.sonar.api.utils.SonarException; | |||
@@ -31,13 +32,9 @@ import java.io.Writer; | |||
/** | |||
* @since 2.3 | |||
*/ | |||
public final class XMLProfileExporter { | |||
public final class XMLProfileSerializer implements ServerComponent { | |||
public static XMLProfileExporter create() { | |||
return new XMLProfileExporter(); | |||
} | |||
public void exportProfile(RulesProfile profile, Writer writer) { | |||
public void write(RulesProfile profile, Writer writer) { | |||
try { | |||
appendHeader(profile, writer); | |||
appendRules(profile, writer); |
@@ -41,7 +41,7 @@ public abstract class ModelDefinition implements ServerExtension { | |||
return name; | |||
} | |||
public abstract Model create(); | |||
public abstract Model createModel(); | |||
@Override | |||
public final boolean equals(Object o) { |
@@ -1,74 +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.api.profiles; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import org.sonar.check.BelongsToProfile; | |||
import org.sonar.check.Check; | |||
import org.sonar.check.IsoCategory; | |||
import org.sonar.check.Priority; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.junit.Assert.assertThat; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class AnnotationProfileDefinitionTest { | |||
@Test | |||
public void importProfile() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.findByKey(anyString(), anyString())).thenAnswer(new Answer<Rule>(){ | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
return Rule.create((String)iom.getArguments()[0], (String)iom.getArguments()[1], (String)iom.getArguments()[1]); | |||
} | |||
}); | |||
ProfileDefinition definition = new FakeDefinition(ruleFinder); | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RulesProfile profile = definition.createProfile(validation); | |||
assertThat(profile.getActiveRule("squid", "fake").getPriority(), is(RulePriority.BLOCKER)); | |||
assertThat(validation.hasErrors(), is(false)); | |||
} | |||
} | |||
@BelongsToProfile(title = "not used !", priority = Priority.BLOCKER) | |||
@Check(key = "fake", isoCategory = IsoCategory.Efficiency, priority = Priority.CRITICAL) | |||
class FakeRule { | |||
} | |||
class FakeDefinition extends AnnotationProfileDefinition { | |||
public FakeDefinition(RuleFinder ruleFinder) { | |||
super("squid", "sonar way", "java", Arrays.<Class>asList(FakeRule.class), ruleFinder); | |||
} | |||
} |
@@ -0,0 +1,85 @@ | |||
/* | |||
* 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.api.profiles; | |||
import com.google.common.collect.Lists; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RuleFinder; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import org.sonar.check.BelongsToProfile; | |||
import org.sonar.check.IsoCategory; | |||
import org.sonar.check.Priority; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.junit.Assert.*; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class AnnotationProfileParserTest { | |||
@Test | |||
public void shouldParseAnnotatedClasses() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.findByKey(anyString(), anyString())).thenAnswer(new Answer<Rule>() { | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
return Rule.create((String) iom.getArguments()[0], (String) iom.getArguments()[1], (String) iom.getArguments()[1]); | |||
} | |||
}); | |||
ValidationMessages messages = ValidationMessages.create(); | |||
RulesProfile profile = new AnnotationProfileParser(ruleFinder).parse("squid", "Foo way", "java", Lists.<Class>newArrayList(FakeRule.class), messages); | |||
assertThat(profile.getName(), is("Foo way")); | |||
assertThat(profile.getLanguage(), is("java")); | |||
assertThat(profile.getActiveRule("squid", "fake").getPriority(), is(RulePriority.BLOCKER)); | |||
assertThat(messages.hasErrors(), is(false)); | |||
} | |||
@Test | |||
public void shouldParseOnlyWantedProfile() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.findByKey(anyString(), anyString())).thenAnswer(new Answer<Rule>() { | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
return Rule.create((String) iom.getArguments()[0], (String) iom.getArguments()[1], (String) iom.getArguments()[1]); | |||
} | |||
}); | |||
ValidationMessages messages = ValidationMessages.create(); | |||
RulesProfile profile = new AnnotationProfileParser(ruleFinder).parse("squid", "Foo way", "java", Lists.<Class>newArrayList(FakeRule.class, RuleOnOtherProfile.class), messages); | |||
assertNotNull(profile.getActiveRule("squid", "fake")); | |||
assertNull(profile.getActiveRule("squid", "other")); | |||
} | |||
} | |||
@BelongsToProfile(title = "Other profile", priority = Priority.BLOCKER) | |||
@org.sonar.check.Rule(key = "other", isoCategory = IsoCategory.Efficiency, priority = Priority.CRITICAL) | |||
class RuleOnOtherProfile { | |||
} | |||
@BelongsToProfile(title = "Foo way", priority = Priority.BLOCKER) | |||
@org.sonar.check.Rule(key = "fake", isoCategory = IsoCategory.Efficiency, priority = Priority.CRITICAL) | |||
class FakeRule { | |||
} |
@@ -1,131 +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.api.profiles; | |||
import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.lang.CharEncoding; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
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.utils.ValidationMessages; | |||
import java.io.InputStreamReader; | |||
import java.io.Reader; | |||
import java.io.UnsupportedEncodingException; | |||
import static org.hamcrest.CoreMatchers.nullValue; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertThat; | |||
import static org.junit.internal.matchers.StringContains.containsString; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class XMLProfileImporterTest { | |||
@Test | |||
public void importProfile() throws UnsupportedEncodingException { | |||
Reader reader = new InputStreamReader(getClass().getResourceAsStream("/org/sonar/api/profiles/XMLProfileImporterTest/importProfile.xml"), CharEncoding.UTF_8); | |||
try { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
RulesProfile profile = XMLProfileImporter.create(ruleFinder).importProfile(reader, validation); | |||
assertThat(profile.getLanguage(), is("java")); | |||
assertThat(profile.getName(), is("sonar way")); | |||
assertThat(validation.hasErrors(), is(false)); | |||
assertNotNull(profile); | |||
assertThat(profile.getActiveRule("checkstyle", "IllegalRegexp").getPriority(), is(RulePriority.CRITICAL)); | |||
} finally { | |||
IOUtils.closeQuietly(reader); | |||
} | |||
} | |||
@Test | |||
public void nameAndLanguageShouldBeMandatory() throws UnsupportedEncodingException { | |||
Reader reader = new InputStreamReader(getClass().getResourceAsStream("/org/sonar/api/profiles/XMLProfileImporterTest/nameAndLanguageShouldBeMandatory.xml"), CharEncoding.UTF_8); | |||
try { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
RulesProfile profile = XMLProfileImporter.create(ruleFinder).importProfile(reader, validation); | |||
assertThat(validation.getErrors().size(), is(2)); | |||
assertThat(validation.getErrors().get(0) , containsString("")); | |||
} finally { | |||
IOUtils.closeQuietly(reader); | |||
} | |||
} | |||
@Test | |||
public void importProfileWithRuleParameters() throws UnsupportedEncodingException { | |||
Reader reader = new InputStreamReader(getClass().getResourceAsStream("/org/sonar/api/profiles/XMLProfileImporterTest/importProfileWithRuleParameters.xml"), CharEncoding.UTF_8); | |||
try { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
RulesProfile profile = XMLProfileImporter.create(ruleFinder).importProfile(reader, validation); | |||
assertThat(validation.hasErrors(), is(false)); | |||
assertThat(validation.hasWarnings(), is(false)); | |||
ActiveRule rule = profile.getActiveRule("checkstyle", "IllegalRegexp"); | |||
assertThat(rule.getParameter("format"), is("foo")); | |||
assertThat(rule.getParameter("message"), is("with special characters < > &")); | |||
} finally { | |||
IOUtils.closeQuietly(reader); | |||
} | |||
} | |||
@Test | |||
public void importProfileWithUnknownRuleParameter() throws UnsupportedEncodingException { | |||
Reader reader = new InputStreamReader(getClass().getResourceAsStream("/org/sonar/api/profiles/XMLProfileImporterTest/importProfileWithUnknownRuleParameter.xml"), CharEncoding.UTF_8); | |||
try { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
RulesProfile profile = XMLProfileImporter.create(ruleFinder).importProfile(reader, validation); | |||
assertThat(validation.getWarnings().size(), is(1)); | |||
ActiveRule rule = profile.getActiveRule("checkstyle", "IllegalRegexp"); | |||
assertThat(rule.getParameter("unknown"), nullValue()); | |||
} finally { | |||
IOUtils.closeQuietly(reader); | |||
} | |||
} | |||
private RuleFinder newRuleFinder() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.findByKey(anyString(), anyString())).thenAnswer(new Answer<Rule>(){ | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
Rule rule = Rule.create((String) iom.getArguments()[0], (String) iom.getArguments()[1], (String) iom.getArguments()[1]); | |||
rule.createParameter("format"); | |||
rule.createParameter("message"); | |||
return rule; | |||
} | |||
}); | |||
return ruleFinder; | |||
} | |||
} |
@@ -0,0 +1,104 @@ | |||
/* | |||
* 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.api.profiles; | |||
import org.junit.Test; | |||
import org.mockito.invocation.InvocationOnMock; | |||
import org.mockito.stubbing.Answer; | |||
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.utils.ValidationMessages; | |||
import java.io.UnsupportedEncodingException; | |||
import static org.hamcrest.CoreMatchers.nullValue; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.junit.Assert.assertNotNull; | |||
import static org.junit.Assert.assertThat; | |||
import static org.junit.internal.matchers.StringContains.containsString; | |||
import static org.mockito.Matchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class XMLProfileParserTest { | |||
@Test | |||
public void importProfile() throws UnsupportedEncodingException { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
RulesProfile profile = new XMLProfileParser(ruleFinder).parseResource(getClass().getClassLoader(), "org/sonar/api/profiles/XMLProfileParserTest/importProfile.xml", validation); | |||
assertThat(profile.getLanguage(), is("java")); | |||
assertThat(profile.getName(), is("sonar way")); | |||
assertThat(validation.hasErrors(), is(false)); | |||
assertNotNull(profile); | |||
assertThat(profile.getActiveRule("checkstyle", "IllegalRegexp").getPriority(), is(RulePriority.CRITICAL)); | |||
} | |||
@Test | |||
public void nameAndLanguageShouldBeMandatory() throws UnsupportedEncodingException { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
RulesProfile profile = new XMLProfileParser(ruleFinder).parseResource(getClass().getClassLoader(), "org/sonar/api/profiles/XMLProfileParserTest/nameAndLanguageShouldBeMandatory.xml", validation); | |||
assertThat(validation.getErrors().size(), is(2)); | |||
assertThat(validation.getErrors().get(0), containsString("")); | |||
} | |||
@Test | |||
public void importProfileWithRuleParameters() throws UnsupportedEncodingException { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
RulesProfile profile = new XMLProfileParser(ruleFinder).parseResource(getClass().getClassLoader(), "org/sonar/api/profiles/XMLProfileParserTest/importProfileWithRuleParameters.xml", validation); | |||
assertThat(validation.hasErrors(), is(false)); | |||
assertThat(validation.hasWarnings(), is(false)); | |||
ActiveRule rule = profile.getActiveRule("checkstyle", "IllegalRegexp"); | |||
assertThat(rule.getParameter("format"), is("foo")); | |||
assertThat(rule.getParameter("message"), is("with special characters < > &")); | |||
} | |||
@Test | |||
public void importProfileWithUnknownRuleParameter() throws UnsupportedEncodingException { | |||
ValidationMessages validation = ValidationMessages.create(); | |||
RuleFinder ruleFinder = newRuleFinder(); | |||
RulesProfile profile = new XMLProfileParser(ruleFinder).parseResource(getClass().getClassLoader(), "org/sonar/api/profiles/XMLProfileParserTest/importProfileWithUnknownRuleParameter.xml", validation); | |||
assertThat(validation.getWarnings().size(), is(1)); | |||
ActiveRule rule = profile.getActiveRule("checkstyle", "IllegalRegexp"); | |||
assertThat(rule.getParameter("unknown"), nullValue()); | |||
} | |||
private RuleFinder newRuleFinder() { | |||
RuleFinder ruleFinder = mock(RuleFinder.class); | |||
when(ruleFinder.findByKey(anyString(), anyString())).thenAnswer(new Answer<Rule>() { | |||
public Rule answer(InvocationOnMock iom) throws Throwable { | |||
Rule rule = Rule.create((String) iom.getArguments()[0], (String) iom.getArguments()[1], (String) iom.getArguments()[1]); | |||
rule.createParameter("format"); | |||
rule.createParameter("message"); | |||
return rule; | |||
} | |||
}); | |||
return ruleFinder; | |||
} | |||
} |
@@ -36,15 +36,15 @@ import java.io.Writer; | |||
import static org.junit.Assert.assertTrue; | |||
public class XMLProfileExporterTest { | |||
public class XMLProfileSerializerTest { | |||
@Test | |||
public void exportEmptyProfile() throws IOException, SAXException { | |||
Writer writer = new StringWriter(); | |||
RulesProfile profile = RulesProfile.create("sonar way", "java"); | |||
XMLProfileExporter.create().exportProfile(profile, writer); | |||
new XMLProfileSerializer().write(profile, writer); | |||
assertSimilarXml("/org/sonar/api/profiles/XMLProfileExporterTest/exportEmptyProfile.xml", writer.toString()); | |||
assertSimilarXml("/org/sonar/api/profiles/XMLProfileSerializerTest/exportEmptyProfile.xml", writer.toString()); | |||
} | |||
@Test | |||
@@ -52,9 +52,9 @@ public class XMLProfileExporterTest { | |||
Writer writer = new StringWriter(); | |||
RulesProfile profile = RulesProfile.create("sonar way", "java"); | |||
profile.activateRule(Rule.create("checkstyle", "IllegalRegexp", "illegal regexp"), RulePriority.BLOCKER); | |||
XMLProfileExporter.create().exportProfile(profile, writer); | |||
new XMLProfileSerializer().write(profile, writer); | |||
assertSimilarXml("/org/sonar/api/profiles/XMLProfileExporterTest/exportProfile.xml", writer.toString()); | |||
assertSimilarXml("/org/sonar/api/profiles/XMLProfileSerializerTest/exportProfile.xml", writer.toString()); | |||
} | |||
@Test | |||
@@ -70,13 +70,13 @@ public class XMLProfileExporterTest { | |||
activeRule.setParameter("format", "foo"); | |||
activeRule.setParameter("message", "with special characters < > &"); | |||
// the tokens parameter is not set | |||
XMLProfileExporter.create().exportProfile(profile, writer); | |||
new XMLProfileSerializer().write(profile, writer); | |||
assertSimilarXml("/org/sonar/api/profiles/XMLProfileExporterTest/exportRuleParameters.xml", writer.toString()); | |||
assertSimilarXml("/org/sonar/api/profiles/XMLProfileSerializerTest/exportRuleParameters.xml", writer.toString()); | |||
} | |||
public static void assertSimilarXml(String pathToExpectedXml, String xml) throws IOException, SAXException { | |||
InputStream stream = XMLProfileExporterTest.class.getResourceAsStream(pathToExpectedXml); | |||
InputStream stream = XMLProfileSerializerTest.class.getResourceAsStream(pathToExpectedXml); | |||
try { | |||
Diff diff = isSimilarXml(IOUtils.toString(stream), xml); | |||
String message = "Diff: " + diff.toString() + CharUtils.LF + "XML: " + xml; |
@@ -28,6 +28,9 @@ import org.sonar.api.Plugins; | |||
import org.sonar.api.database.configuration.DatabaseConfiguration; | |||
import org.sonar.api.platform.Environment; | |||
import org.sonar.api.platform.Server; | |||
import org.sonar.api.profiles.AnnotationProfileParser; | |||
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.utils.HttpDownloader; | |||
@@ -169,6 +172,9 @@ public final class Platform { | |||
servicesContainer.as(Characteristics.NO_CACHE).addComponent(Backup.class); | |||
servicesContainer.as(Characteristics.CACHE).addComponent(AuthenticatorFactory.class); | |||
servicesContainer.as(Characteristics.CACHE).addComponent(ServerLifecycleNotifier.class); | |||
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(DefaultRuleFinder.class); | |||
servicesContainer.as(Characteristics.CACHE).addComponent(DeprecatedRuleRepositories.class); | |||
servicesContainer.as(Characteristics.CACHE).addComponent(DeprecatedProfiles.class); |
@@ -57,7 +57,7 @@ public final class DefaultModelManager implements ServerComponent, ModelManager | |||
for (ModelDefinition definition : definitions) { | |||
if (StringUtils.isNotBlank(definition.getName()) && !exists(session, definition.getName())) { | |||
Logs.INFO.info("Register quality model: " + definition.getName()); | |||
Model model = definition.create(); | |||
Model model = definition.createModel(); | |||
if (StringUtils.isBlank(model.getName())) { | |||
model.setName(definition.getName()); | |||
} | |||
@@ -75,7 +75,7 @@ public final class DefaultModelManager implements ServerComponent, ModelManager | |||
} | |||
LoggerFactory.getLogger(getClass()).info("Reset quality model: " + name); | |||
Model model = definition.create(); | |||
Model model = definition.createModel(); | |||
return reset(model); | |||
} | |||
@@ -40,14 +40,16 @@ import java.util.List; | |||
public final class ProfilesConsole implements ServerComponent { | |||
private DatabaseSessionFactory sessionFactory; | |||
private RuleFinder ruleFinder; | |||
private XMLProfileParser xmlProfileParser; | |||
private XMLProfileSerializer xmlProfileSerializer; | |||
private List<ProfileExporter> exporters = new ArrayList<ProfileExporter>(); | |||
private List<ProfileImporter> importers = new ArrayList<ProfileImporter>(); | |||
public ProfilesConsole(DatabaseSessionFactory sessionFactory, RuleFinder ruleFinder, | |||
public ProfilesConsole(DatabaseSessionFactory sessionFactory, XMLProfileParser xmlProfileParser, XMLProfileSerializer xmlProfileSerializer, | |||
ProfileExporter[] exporters, DeprecatedProfileExporters deprecatedExporters, | |||
ProfileImporter[] importers, DeprecatedProfileImporters deprecatedImporters) { | |||
this.ruleFinder = ruleFinder; | |||
this.xmlProfileParser = xmlProfileParser; | |||
this.xmlProfileSerializer = xmlProfileSerializer; | |||
this.sessionFactory = sessionFactory; | |||
initProfileExporters(exporters, deprecatedExporters); | |||
initProfileImporters(importers, deprecatedImporters); | |||
@@ -72,7 +74,7 @@ public final class ProfilesConsole implements ServerComponent { | |||
RulesProfile profile = loadProfile(session, profileId); | |||
if (profile != null) { | |||
Writer writer = new StringWriter(); | |||
XMLProfileExporter.create().exportProfile(profile, writer); | |||
xmlProfileSerializer.write(profile, writer); | |||
return writer.toString(); | |||
} | |||
return null; | |||
@@ -80,7 +82,7 @@ public final class ProfilesConsole implements ServerComponent { | |||
public ValidationMessages restoreProfile(String xmlBackup) { | |||
ValidationMessages messages = ValidationMessages.create(); | |||
RulesProfile profile = XMLProfileImporter.create(ruleFinder).importProfile(new StringReader(xmlBackup), messages); | |||
RulesProfile profile = xmlProfileParser.parse(new StringReader(xmlBackup), messages); | |||
if (profile != null) { | |||
DatabaseSession session = sessionFactory.getSession(); | |||
RulesProfile existingProfile = session.getSingleResult(RulesProfile.class, "name", profile.getName(), "language", profile.getLanguage()); |
@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.server.startup; | |||
import com.google.common.collect.Lists; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.slf4j.Logger; | |||
import org.slf4j.LoggerFactory; | |||
@@ -40,7 +41,7 @@ public final class RegisterProvidedProfiles { | |||
private static final Logger LOGGER = LoggerFactory.getLogger(RegisterProvidedProfiles.class); | |||
private DatabaseSessionFactory sessionFactory; | |||
private List<ProfileDefinition> definitions = new ArrayList<ProfileDefinition>(); | |||
private List<ProfileDefinition> definitions = Lists.newArrayList(); | |||
private DeprecatedProfiles deprecatedProfiles = null; | |||
private RuleFinder ruleFinder; | |||
@@ -71,7 +72,7 @@ public final class RegisterProvidedProfiles { | |||
} | |||
List<RulesProfile> createProfiles() { | |||
List<RulesProfile> result = new ArrayList<RulesProfile>(); | |||
List<RulesProfile> result = Lists.newArrayList(); | |||
// this must not be moved in the constructor, because rules are still not saved | |||
definitions.addAll(deprecatedProfiles.getProfiles()); |
@@ -114,7 +114,7 @@ class FakeDefinition extends ModelDefinition { | |||
} | |||
@Override | |||
public Model create() { | |||
public Model createModel() { | |||
return model; | |||
} | |||
@@ -23,7 +23,6 @@ import org.junit.Test; | |||
import org.sonar.api.rules.Rule; | |||
import org.sonar.api.rules.RulePriority; | |||
import org.sonar.api.utils.ValidationMessages; | |||
import org.sonar.server.rules.DeprecatedProfiles; | |||
import static org.hamcrest.Matchers.is; | |||
import static org.hamcrest.core.IsNull.nullValue; | |||
@@ -31,7 +30,7 @@ import static org.junit.Assert.assertThat; | |||
public class DeprecatedProfilesTest { | |||
@Test | |||
public void testCreate() { | |||
public void shouldCreateProfile() { | |||
DeprecatedProfiles.DefaultProfileDefinition def = DeprecatedProfiles.DefaultProfileDefinition.create("sonar way", "java"); | |||
assertThat(def.createProfile(ValidationMessages.create()).getName(), is("sonar way")); | |||
assertThat(def.createProfile(ValidationMessages.create()).getLanguage(), is("java")); |