From d1c26036280d4513835de01dca1893f652d51413 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Mon, 24 Mar 2014 18:01:30 +0100 Subject: SONAR-4908 extract RulesDefinitionXmlLoader --- .../api/server/rule/RuleDefinitionsFromXml.java | 196 ----------------- .../org/sonar/api/server/rule/RulesDefinition.java | 81 +++---- .../api/server/rule/RulesDefinitionXmlLoader.java | 234 +++++++++++++++++++++ .../server/rule/RulesDefinitionFromXmlTest.java | 125 ----------- .../server/rule/RulesDefinitionXmlLoaderTest.java | 133 ++++++++++++ .../rule/RuleDefinitionsFromXmlTest/deprecated.xml | 10 - .../rule/RuleDefinitionsFromXmlTest/rules.xml | 41 ---- .../rule/RuleDefinitionsFromXmlTest/utf8.xml | 11 - .../RulesDefinitionXmlLoaderTest/deprecated.xml | 10 + .../rule/RulesDefinitionXmlLoaderTest/invalid.xml | 2 + .../rule/RulesDefinitionXmlLoaderTest/rules.xml | 41 ++++ .../rule/RulesDefinitionXmlLoaderTest/utf8.xml | 11 + 12 files changed, 461 insertions(+), 434 deletions(-) delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleDefinitionsFromXml.java create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java delete mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionFromXmlTest.java create mode 100644 sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest.java delete mode 100644 sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/deprecated.xml delete mode 100644 sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/rules.xml delete mode 100644 sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/utf8.xml create mode 100644 sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/deprecated.xml create mode 100644 sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/invalid.xml create mode 100644 sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/rules.xml create mode 100644 sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/utf8.xml (limited to 'sonar-plugin-api/src') diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleDefinitionsFromXml.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleDefinitionsFromXml.java deleted file mode 100644 index 80b9bec7e06..00000000000 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleDefinitionsFromXml.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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 this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.api.server.rule; - -import com.google.common.io.Closeables; -import org.apache.commons.lang.StringUtils; -import org.codehaus.staxmate.SMInputFactory; -import org.codehaus.staxmate.in.SMHierarchicCursor; -import org.codehaus.staxmate.in.SMInputCursor; -import org.sonar.api.rule.RuleStatus; -import org.sonar.api.rule.Severity; -import org.sonar.check.Cardinality; - -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.ArrayList; -import java.util.List; - -/** - * @since 4.2 - */ -class RuleDefinitionsFromXml { - - void loadRules(RulesDefinition.NewRepository repo, InputStream input, String encoding) { - Reader reader = null; - try { - reader = new InputStreamReader(input, encoding); - loadRules(repo, reader); - - } catch (IOException e) { - throw new IllegalStateException("Fail to load XML file", e); - - } finally { - Closeables.closeQuietly(reader); - } - } - - void loadRules(RulesDefinition.NewRepository repo, Reader reader) { - XMLInputFactory xmlFactory = XMLInputFactory.newInstance(); - xmlFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE); - xmlFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE); - // just so it won't try to load DTD in if there's DOCTYPE - xmlFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE); - xmlFactory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE); - SMInputFactory inputFactory = new SMInputFactory(xmlFactory); - try { - SMHierarchicCursor rootC = inputFactory.rootElementCursor(reader); - rootC.advance(); // - - SMInputCursor rulesC = rootC.childElementCursor("rule"); - while (rulesC.getNext() != null) { - // - processRule(repo, rulesC); - } - - } catch (XMLStreamException e) { - throw new IllegalStateException("XML is not valid", e); - } - } - - private void processRule(RulesDefinition.NewRepository repo, SMInputCursor ruleC) throws XMLStreamException { - String key = null, name = null, description = null, internalKey = null, severity = Severity.defaultSeverity(), status = null; - Cardinality cardinality = Cardinality.SINGLE; - List params = new ArrayList(); - List tags = new ArrayList(); - - /* BACKWARD COMPATIBILITY WITH VERY OLD FORMAT */ - String keyAttribute = ruleC.getAttrValue("key"); - if (StringUtils.isNotBlank(keyAttribute)) { - key = StringUtils.trim(keyAttribute); - } - String priorityAttribute = ruleC.getAttrValue("priority"); - if (StringUtils.isNotBlank(priorityAttribute)) { - severity = StringUtils.trim(priorityAttribute); - } - - SMInputCursor cursor = ruleC.childElementCursor(); - while (cursor.getNext() != null) { - String nodeName = cursor.getLocalName(); - - if (StringUtils.equalsIgnoreCase("name", nodeName)) { - name = StringUtils.trim(cursor.collectDescendantText(false)); - - } else if (StringUtils.equalsIgnoreCase("description", nodeName)) { - description = StringUtils.trim(cursor.collectDescendantText(false)); - - } else if (StringUtils.equalsIgnoreCase("key", nodeName)) { - key = StringUtils.trim(cursor.collectDescendantText(false)); - - } else if (StringUtils.equalsIgnoreCase("configKey", nodeName)) { - // deprecated field, replaced by internalKey - internalKey = StringUtils.trim(cursor.collectDescendantText(false)); - - } else if (StringUtils.equalsIgnoreCase("internalKey", nodeName)) { - internalKey = StringUtils.trim(cursor.collectDescendantText(false)); - - } else if (StringUtils.equalsIgnoreCase("priority", nodeName)) { - // deprecated field, replaced by severity - severity = StringUtils.trim(cursor.collectDescendantText(false)); - - } else if (StringUtils.equalsIgnoreCase("severity", nodeName)) { - severity = StringUtils.trim(cursor.collectDescendantText(false)); - - } else if (StringUtils.equalsIgnoreCase("cardinality", nodeName)) { - cardinality = Cardinality.valueOf(StringUtils.trim(cursor.collectDescendantText(false))); - - } else if (StringUtils.equalsIgnoreCase("status", nodeName)) { - status = StringUtils.trim(cursor.collectDescendantText(false)); - - } else if (StringUtils.equalsIgnoreCase("param", nodeName)) { - params.add(processParameter(cursor)); - - } else if (StringUtils.equalsIgnoreCase("tag", nodeName)) { - tags.add(StringUtils.trim(cursor.collectDescendantText(false))); - } - } - RulesDefinition.NewRule rule = repo.createRule(key) - .setHtmlDescription(description) - .setSeverity(severity) - .setName(name) - .setInternalKey(internalKey) - .setTags(tags.toArray(new String[tags.size()])) - .setTemplate(cardinality == Cardinality.MULTIPLE); - if (status != null) { - rule.setStatus(RuleStatus.valueOf(status)); - } - for (ParamStruct param : params) { - rule.createParam(param.key) - .setDefaultValue(param.defaultValue) - .setType(param.type) - .setDescription(param.description); - } - } - - private static class ParamStruct { - String key, description, defaultValue; - RuleParamType type = RuleParamType.STRING; - } - - private ParamStruct processParameter(SMInputCursor ruleC) throws XMLStreamException { - ParamStruct param = new ParamStruct(); - - // BACKWARD COMPATIBILITY WITH DEPRECATED FORMAT - String keyAttribute = ruleC.getAttrValue("key"); - if (StringUtils.isNotBlank(keyAttribute)) { - param.key = StringUtils.trim(keyAttribute); - } - - // BACKWARD COMPATIBILITY WITH DEPRECATED FORMAT - String typeAttribute = ruleC.getAttrValue("type"); - if (StringUtils.isNotBlank(typeAttribute)) { - param.type = RuleParamType.parse(typeAttribute); - } - - SMInputCursor paramC = ruleC.childElementCursor(); - while (paramC.getNext() != null) { - String propNodeName = paramC.getLocalName(); - String propText = StringUtils.trim(paramC.collectDescendantText(false)); - if (StringUtils.equalsIgnoreCase("key", propNodeName)) { - param.key = propText; - - } else if (StringUtils.equalsIgnoreCase("description", propNodeName)) { - param.description = propText; - - } else if (StringUtils.equalsIgnoreCase("type", propNodeName)) { - param.type = RuleParamType.parse(propText); - - } else if (StringUtils.equalsIgnoreCase("defaultValue", propNodeName)) { - param.defaultValue = propText; - } - } - return param; - } -} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java index 45650ecf6c0..2bab880020a 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java @@ -20,7 +20,13 @@ package org.sonar.api.server.rule; import com.google.common.base.Strings; -import com.google.common.collect.*; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSortedSet; +import com.google.common.collect.ListMultimap; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.slf4j.LoggerFactory; @@ -31,10 +37,9 @@ import org.sonar.api.rule.Severity; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; - import java.io.IOException; -import java.io.InputStream; import java.net.URL; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; @@ -107,48 +112,6 @@ public interface RulesDefinition extends ServerExtension { */ NewExtendedRepository loadAnnotatedClasses(Class... classes); - /** - * Reads definitions of rules from a XML file. Format is : - *
-     * <rules>
-     * <rule>
-     * <!-- required fields -->
-     * <key>the-rule-key</key>
-     * <name>The purpose of the rule</name>
-     * <description>
-     * <![CDATA[The description]]>
-     * </description>
-     *
-     * <!-- optional fields -->
-     * <internalKey>Checker/TreeWalker/LocalVariableName</internalKey>
-     * <severity>BLOCKER</severity>
-     * <cardinality>MULTIPLE</cardinality>
-     * <status>BETA</status>
-     * <param>
-     * <key>the-param-key</key>
-     * <tag>style</tag>
-     * <tag>security</tag>
-     * <description>
-     * <![CDATA[
-     * the param-description
-     * ]]>
-     * </description>
-     * <defaultValue>42</defaultValue>
-     * </param>
-     * <param>
-     * <key>another-param</key>
-     * </param>
-     *
-     * <!-- deprecated fields -->
-     * <configKey>Checker/TreeWalker/LocalVariableName</configKey>
-     * <priority>BLOCKER</priority>
-     * </rule>
-     * </rules>
-     *
-     * 
- */ - NewExtendedRepository loadXml(InputStream xmlInput, String encoding); - void done(); } @@ -157,6 +120,10 @@ public interface RulesDefinition extends ServerExtension { @CheckForNull NewRule rule(String ruleKey); + + Collection rules(); + + String key(); } class NewRepositoryImpl implements NewRepository { @@ -174,6 +141,11 @@ public interface RulesDefinition extends ServerExtension { this.language = language; } + @Override + public String key() { + return key; + } + @Override public NewRepositoryImpl setName(@Nullable String s) { if (StringUtils.isNotEmpty(s)) { @@ -201,6 +173,11 @@ public interface RulesDefinition extends ServerExtension { return newRules.get(ruleKey); } + @Override + public Collection rules() { + return newRules.values(); + } + @Override public NewRepositoryImpl loadAnnotatedClasses(Class... classes) { new RuleDefinitionsFromAnnotations().loadRules(this, classes); @@ -212,12 +189,6 @@ public interface RulesDefinition extends ServerExtension { return new RuleDefinitionsFromAnnotations().loadRule(this, clazz); } - @Override - public NewRepositoryImpl loadXml(InputStream xmlInput, String encoding) { - new RuleDefinitionsFromXml().loadRules(this, xmlInput, encoding); - return this; - } - @Override public void done() { // note that some validations can be done here, for example for @@ -409,6 +380,10 @@ public interface RulesDefinition extends ServerExtension { return paramsByKey.get(paramKey); } + public Collection params() { + return paramsByKey.values(); + } + /** * @see RuleTagFormat */ @@ -589,6 +564,10 @@ public interface RulesDefinition extends ServerExtension { this.key = this.name = key; } + public String key() { + return key; + } + public NewParam setName(@Nullable String s) { // name must never be null. this.name = StringUtils.defaultIfBlank(s, key); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java new file mode 100644 index 00000000000..240420d1ee2 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinitionXmlLoader.java @@ -0,0 +1,234 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.server.rule; + +import com.google.common.io.Closeables; +import org.apache.commons.lang.StringUtils; +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.rule.RuleStatus; +import org.sonar.api.rule.Severity; +import org.sonar.check.Cardinality; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; + +/** + * Loads definitions of rules from a XML file. + * + *

XML Format

+ *
+ * <rules>
+ *   <rule>
+ *     <!-- required fields -->
+ *     <key>the-rule-key</key>
+ *     <name>The purpose of the rule</name>
+ *
+ *     <!-- optional fields -->
+ *     <description>
+ *       <![CDATA[The description]]>
+ *     </description>
+ *     <internalKey>Checker/TreeWalker/LocalVariableName</internalKey>
+ *     <severity>BLOCKER</severity>
+ *     <cardinality>MULTIPLE</cardinality>
+ *     <status>BETA</status>
+ *     <param>
+ *       <key>the-param-key</key>
+ *       <tag>style</tag>
+ *       <tag>security</tag>
+ *       <description>
+ *         <![CDATA[the param-description]]>
+ *       </description>
+ *       <defaultValue>42</defaultValue>
+ *     </param>
+ *     <param>
+ *       <key>another-param</key>
+ *     </param>
+ *
+ *     <!-- deprecated fields -->
+ *     <configKey>Checker/TreeWalker/LocalVariableName</configKey>
+ *     <priority>BLOCKER</priority>
+ *   </rule>
+ * </rules>
+ * 
+ * + * @since 4.3 + */ +public class RulesDefinitionXmlLoader implements ServerComponent { + + public void load(RulesDefinition.NewRepository repo, InputStream input, String encoding) { + Reader reader = null; + try { + reader = new InputStreamReader(input, encoding); + load(repo, reader); + + } catch (IOException e) { + throw new IllegalStateException("Fail to load XML file", e); + + } finally { + Closeables.closeQuietly(reader); + } + } + + public void load(RulesDefinition.NewRepository repo, Reader reader) { + XMLInputFactory xmlFactory = XMLInputFactory.newInstance(); + xmlFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE); + xmlFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE); + // just so it won't try to load DTD in if there's DOCTYPE + xmlFactory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE); + xmlFactory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE); + SMInputFactory inputFactory = new SMInputFactory(xmlFactory); + try { + SMHierarchicCursor rootC = inputFactory.rootElementCursor(reader); + rootC.advance(); // + + SMInputCursor rulesC = rootC.childElementCursor("rule"); + while (rulesC.getNext() != null) { + // + processRule(repo, rulesC); + } + + } catch (XMLStreamException e) { + throw new IllegalStateException("XML is not valid", e); + } + } + + private void processRule(RulesDefinition.NewRepository repo, SMInputCursor ruleC) throws XMLStreamException { + String key = null, name = null, description = null, internalKey = null, severity = Severity.defaultSeverity(), status = null; + Cardinality cardinality = Cardinality.SINGLE; + List params = new ArrayList(); + List tags = new ArrayList(); + + /* BACKWARD COMPATIBILITY WITH VERY OLD FORMAT */ + String keyAttribute = ruleC.getAttrValue("key"); + if (StringUtils.isNotBlank(keyAttribute)) { + key = StringUtils.trim(keyAttribute); + } + String priorityAttribute = ruleC.getAttrValue("priority"); + if (StringUtils.isNotBlank(priorityAttribute)) { + severity = StringUtils.trim(priorityAttribute); + } + + SMInputCursor cursor = ruleC.childElementCursor(); + while (cursor.getNext() != null) { + String nodeName = cursor.getLocalName(); + + if (StringUtils.equalsIgnoreCase("name", nodeName)) { + name = StringUtils.trim(cursor.collectDescendantText(false)); + + } else if (StringUtils.equalsIgnoreCase("description", nodeName)) { + description = StringUtils.trim(cursor.collectDescendantText(false)); + + } else if (StringUtils.equalsIgnoreCase("key", nodeName)) { + key = StringUtils.trim(cursor.collectDescendantText(false)); + + } else if (StringUtils.equalsIgnoreCase("configKey", nodeName)) { + // deprecated field, replaced by internalKey + internalKey = StringUtils.trim(cursor.collectDescendantText(false)); + + } else if (StringUtils.equalsIgnoreCase("internalKey", nodeName)) { + internalKey = StringUtils.trim(cursor.collectDescendantText(false)); + + } else if (StringUtils.equalsIgnoreCase("priority", nodeName)) { + // deprecated field, replaced by severity + severity = StringUtils.trim(cursor.collectDescendantText(false)); + + } else if (StringUtils.equalsIgnoreCase("severity", nodeName)) { + severity = StringUtils.trim(cursor.collectDescendantText(false)); + + } else if (StringUtils.equalsIgnoreCase("cardinality", nodeName)) { + cardinality = Cardinality.valueOf(StringUtils.trim(cursor.collectDescendantText(false))); + + } else if (StringUtils.equalsIgnoreCase("status", nodeName)) { + status = StringUtils.trim(cursor.collectDescendantText(false)); + + } else if (StringUtils.equalsIgnoreCase("param", nodeName)) { + params.add(processParameter(cursor)); + + } else if (StringUtils.equalsIgnoreCase("tag", nodeName)) { + tags.add(StringUtils.trim(cursor.collectDescendantText(false))); + } + } + RulesDefinition.NewRule rule = repo.createRule(key) + .setHtmlDescription(description) + .setSeverity(severity) + .setName(name) + .setInternalKey(internalKey) + .setTags(tags.toArray(new String[tags.size()])) + .setTemplate(cardinality == Cardinality.MULTIPLE); + if (status != null) { + rule.setStatus(RuleStatus.valueOf(status)); + } + for (ParamStruct param : params) { + rule.createParam(param.key) + .setDefaultValue(param.defaultValue) + .setType(param.type) + .setDescription(param.description); + } + } + + private static class ParamStruct { + String key, description, defaultValue; + RuleParamType type = RuleParamType.STRING; + } + + private ParamStruct processParameter(SMInputCursor ruleC) throws XMLStreamException { + ParamStruct param = new ParamStruct(); + + // BACKWARD COMPATIBILITY WITH DEPRECATED FORMAT + String keyAttribute = ruleC.getAttrValue("key"); + if (StringUtils.isNotBlank(keyAttribute)) { + param.key = StringUtils.trim(keyAttribute); + } + + // BACKWARD COMPATIBILITY WITH DEPRECATED FORMAT + String typeAttribute = ruleC.getAttrValue("type"); + if (StringUtils.isNotBlank(typeAttribute)) { + param.type = RuleParamType.parse(typeAttribute); + } + + SMInputCursor paramC = ruleC.childElementCursor(); + while (paramC.getNext() != null) { + String propNodeName = paramC.getLocalName(); + String propText = StringUtils.trim(paramC.collectDescendantText(false)); + if (StringUtils.equalsIgnoreCase("key", propNodeName)) { + param.key = propText; + + } else if (StringUtils.equalsIgnoreCase("description", propNodeName)) { + param.description = propText; + + } else if (StringUtils.equalsIgnoreCase("type", propNodeName)) { + param.type = RuleParamType.parse(propText); + + } else if (StringUtils.equalsIgnoreCase("defaultValue", propNodeName)) { + param.defaultValue = propText; + } + } + return param; + } +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionFromXmlTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionFromXmlTest.java deleted file mode 100644 index 8be35912749..00000000000 --- a/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionFromXmlTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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 this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.api.server.rule; - -import com.google.common.base.Charsets; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.rule.RuleStatus; -import org.sonar.api.rule.Severity; - -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; -import java.io.UnsupportedEncodingException; - -import static org.fest.assertions.Assertions.assertThat; - -public class RulesDefinitionFromXmlTest { - - @org.junit.Rule - public final ExpectedException thrown = ExpectedException.none(); - - private RulesDefinition.Repository load(Reader reader) { - RulesDefinition.Context context = new RulesDefinition.Context(); - RulesDefinition.NewRepository newRepository = context.createRepository("squid", "java"); - new RuleDefinitionsFromXml().loadRules(newRepository, reader); - newRepository.done(); - return context.repository("squid"); - } - - @Test - public void should_parse_xml() throws Exception { - InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream("/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/rules.xml"), Charsets.UTF_8.name()); - RulesDefinition.Repository repository = load(reader); - assertThat(repository.rules()).hasSize(2); - - RulesDefinition.Rule rule = repository.rule("complete"); - assertThat(rule.key()).isEqualTo("complete"); - assertThat(rule.name()).isEqualTo("Complete"); - assertThat(rule.htmlDescription()).isEqualTo("Description of Complete"); - assertThat(rule.severity()).isEqualTo(Severity.BLOCKER); - assertThat(rule.template()).isTrue(); - assertThat(rule.status()).isEqualTo(RuleStatus.BETA); - assertThat(rule.internalKey()).isEqualTo("Checker/TreeWalker/LocalVariableName"); - assertThat(rule.tags()).containsOnly("style", "security"); - - assertThat(rule.params()).hasSize(2); - RulesDefinition.Param ignore = rule.param("ignore"); - assertThat(ignore.key()).isEqualTo("ignore"); - assertThat(ignore.description()).isEqualTo("Ignore ?"); - assertThat(ignore.defaultValue()).isEqualTo("false"); - - rule = repository.rule("minimal"); - assertThat(rule.key()).isEqualTo("minimal"); - assertThat(rule.name()).isEqualTo("Minimal"); - assertThat(rule.htmlDescription()).isEqualTo("Description of Minimal"); - assertThat(rule.params()).isEmpty(); - assertThat(rule.status()).isEqualTo(RuleStatus.READY); - assertThat(rule.severity()).isEqualTo(Severity.MAJOR); - } - - @Test - public void should_fail_if_missing_rule_key() { - thrown.expect(IllegalStateException.class); - load(new StringReader("Foo")); - } - - @Test - public void should_fail_if_missing_property_key() { - thrown.expect(IllegalStateException.class); - load(new StringReader("fooFoo")); - } - - @Test - public void should_fail_on_invalid_rule_parameter_type() { - thrown.expect(IllegalStateException.class); - load(new StringReader("fooFookeyINVALID")); - } - - @Test - public void test_utf8_encoding() throws UnsupportedEncodingException { - InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream("/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/utf8.xml"), Charsets.UTF_8.name()); - RulesDefinition.Repository repository = load(reader); - - assertThat(repository.rules()).hasSize(1); - RulesDefinition.Rule rule = repository.rules().get(0); - assertThat(rule.key()).isEqualTo("com.puppycrawl.tools.checkstyle.checks.naming.LocalVariableNameCheck"); - assertThat(rule.name()).isEqualTo("M & M"); - assertThat(rule.htmlDescription().charAt(0)).isEqualTo('\u00E9'); - assertThat(rule.htmlDescription().charAt(1)).isEqualTo('\u00E0'); - assertThat(rule.htmlDescription().charAt(2)).isEqualTo('\u0026'); - } - - @Test - public void should_support_deprecated_format() throws UnsupportedEncodingException { - // the deprecated format uses some attributes instead of nodes - InputStreamReader reader = new InputStreamReader(getClass().getResourceAsStream("/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/deprecated.xml"), Charsets.UTF_8.name()); - RulesDefinition.Repository repository = load(reader); - - assertThat(repository.rules()).hasSize(1); - RulesDefinition.Rule rule = repository.rules().get(0); - assertThat(rule.key()).isEqualTo("org.sonar.it.checkstyle.MethodsCountCheck"); - assertThat(rule.internalKey()).isEqualTo("Checker/TreeWalker/org.sonar.it.checkstyle.MethodsCountCheck"); - assertThat(rule.severity()).isEqualTo(Severity.CRITICAL); - assertThat(rule.htmlDescription()).isEqualTo("Count methods"); - assertThat(rule.param("minMethodsCount")).isNotNull(); - } -} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest.java new file mode 100644 index 00000000000..df6ff3bdc85 --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest.java @@ -0,0 +1,133 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.server.rule; + +import com.google.common.base.Charsets; +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rule.Severity; + +import java.io.InputStream; +import java.io.UnsupportedEncodingException; + +import static org.fest.assertions.Assertions.assertThat; + +public class RulesDefinitionXmlLoaderTest { + + @org.junit.Rule + public final ExpectedException thrown = ExpectedException.none(); + + private RulesDefinition.Repository load(InputStream input, String encoding) { + RulesDefinition.Context context = new RulesDefinition.Context(); + RulesDefinition.NewRepository newRepository = context.createRepository("squid", "java"); + new RulesDefinitionXmlLoader().load(newRepository, input, encoding); + newRepository.done(); + return context.repository("squid"); + } + + @Test + public void parse_xml() throws Exception { + InputStream input = getClass().getResourceAsStream("/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/rules.xml"); + RulesDefinition.Repository repository = load(input, Charsets.UTF_8.name()); + assertThat(repository.rules()).hasSize(2); + + RulesDefinition.Rule rule = repository.rule("complete"); + assertThat(rule.key()).isEqualTo("complete"); + assertThat(rule.name()).isEqualTo("Complete"); + assertThat(rule.htmlDescription()).isEqualTo("Description of Complete"); + assertThat(rule.severity()).isEqualTo(Severity.BLOCKER); + assertThat(rule.template()).isTrue(); + assertThat(rule.status()).isEqualTo(RuleStatus.BETA); + assertThat(rule.internalKey()).isEqualTo("Checker/TreeWalker/LocalVariableName"); + assertThat(rule.tags()).containsOnly("style", "security"); + + assertThat(rule.params()).hasSize(2); + RulesDefinition.Param ignore = rule.param("ignore"); + assertThat(ignore.key()).isEqualTo("ignore"); + assertThat(ignore.description()).isEqualTo("Ignore ?"); + assertThat(ignore.defaultValue()).isEqualTo("false"); + + rule = repository.rule("minimal"); + assertThat(rule.key()).isEqualTo("minimal"); + assertThat(rule.name()).isEqualTo("Minimal"); + assertThat(rule.htmlDescription()).isEqualTo("Description of Minimal"); + assertThat(rule.params()).isEmpty(); + assertThat(rule.status()).isEqualTo(RuleStatus.READY); + assertThat(rule.severity()).isEqualTo(Severity.MAJOR); + } + + @Test + public void fail_if_missing_rule_key() { + thrown.expect(IllegalStateException.class); + load(IOUtils.toInputStream("Foo"), Charsets.UTF_8.name()); + } + + @Test + public void fail_if_missing_property_key() { + thrown.expect(IllegalStateException.class); + load(IOUtils.toInputStream("fooFoo"), Charsets.UTF_8.name()); + } + + @Test + public void fail_on_invalid_rule_parameter_type() { + thrown.expect(IllegalStateException.class); + load(IOUtils.toInputStream("fooFookeyINVALID"), Charsets.UTF_8.name()); + } + + @Test + public void fail_if_invalid_xml() throws UnsupportedEncodingException { + thrown.expect(IllegalStateException.class); + thrown.expectMessage("XML is not valid"); + + InputStream input = getClass().getResourceAsStream("/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/invalid.xml"); + load(input, Charsets.UTF_8.name()); + } + + @Test + public void test_utf8_encoding() throws UnsupportedEncodingException { + InputStream input = getClass().getResourceAsStream("/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/utf8.xml"); + RulesDefinition.Repository repository = load(input, Charsets.UTF_8.name()); + + assertThat(repository.rules()).hasSize(1); + RulesDefinition.Rule rule = repository.rules().get(0); + assertThat(rule.key()).isEqualTo("com.puppycrawl.tools.checkstyle.checks.naming.LocalVariableNameCheck"); + assertThat(rule.name()).isEqualTo("M & M"); + assertThat(rule.htmlDescription().charAt(0)).isEqualTo('\u00E9'); + assertThat(rule.htmlDescription().charAt(1)).isEqualTo('\u00E0'); + assertThat(rule.htmlDescription().charAt(2)).isEqualTo('\u0026'); + } + + @Test + public void support_deprecated_format() throws UnsupportedEncodingException { + // the deprecated format uses some attributes instead of nodes + InputStream input = getClass().getResourceAsStream("/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/deprecated.xml"); + RulesDefinition.Repository repository = load(input, Charsets.UTF_8.name()); + + assertThat(repository.rules()).hasSize(1); + RulesDefinition.Rule rule = repository.rules().get(0); + assertThat(rule.key()).isEqualTo("org.sonar.it.checkstyle.MethodsCountCheck"); + assertThat(rule.internalKey()).isEqualTo("Checker/TreeWalker/org.sonar.it.checkstyle.MethodsCountCheck"); + assertThat(rule.severity()).isEqualTo(Severity.CRITICAL); + assertThat(rule.htmlDescription()).isEqualTo("Count methods"); + assertThat(rule.param("minMethodsCount")).isNotNull(); + } +} diff --git a/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/deprecated.xml b/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/deprecated.xml deleted file mode 100644 index 2938ea70377..00000000000 --- a/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/deprecated.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - Methods Count Check - Checker/TreeWalker/org.sonar.it.checkstyle.MethodsCountCheck - Count methods - - description of param - - - \ No newline at end of file diff --git a/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/rules.xml b/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/rules.xml deleted file mode 100644 index 28ea7019c6e..00000000000 --- a/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/rules.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - complete - Complete - - - - Checker/TreeWalker/LocalVariableName - BLOCKER - MULTIPLE - BETA - style - security - - tokens - - - - - - ignore - - Ignore ? - - false - - - - - - - minimal - Minimal - - - - - diff --git a/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/utf8.xml b/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/utf8.xml deleted file mode 100644 index 6197e030057..00000000000 --- a/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RuleDefinitionsFromXmlTest/utf8.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - com.puppycrawl.tools.checkstyle.checks.naming.LocalVariableNameCheck - BLOCKER - Checker/TreeWalker/LocalVariableName - M & M - - - - - diff --git a/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/deprecated.xml b/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/deprecated.xml new file mode 100644 index 00000000000..2938ea70377 --- /dev/null +++ b/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/deprecated.xml @@ -0,0 +1,10 @@ + + + Methods Count Check + Checker/TreeWalker/org.sonar.it.checkstyle.MethodsCountCheck + Count methods + + description of param + + + \ No newline at end of file diff --git a/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/invalid.xml b/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/invalid.xml new file mode 100644 index 00000000000..de3d00c00aa --- /dev/null +++ b/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/invalid.xml @@ -0,0 +1,2 @@ + + diff --git a/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/rules.xml b/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/rules.xml new file mode 100644 index 00000000000..28ea7019c6e --- /dev/null +++ b/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/rules.xml @@ -0,0 +1,41 @@ + + + + complete + Complete + + + + Checker/TreeWalker/LocalVariableName + BLOCKER + MULTIPLE + BETA + style + security + + tokens + + + + + + ignore + + Ignore ? + + false + + + + + + + minimal + Minimal + + + + + diff --git a/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/utf8.xml b/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/utf8.xml new file mode 100644 index 00000000000..6197e030057 --- /dev/null +++ b/sonar-plugin-api/src/test/resources/org/sonar/api/server/rule/RulesDefinitionXmlLoaderTest/utf8.xml @@ -0,0 +1,11 @@ + + + com.puppycrawl.tools.checkstyle.checks.naming.LocalVariableNameCheck + BLOCKER + Checker/TreeWalker/LocalVariableName + M & M + + + + + -- cgit v1.2.3