]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6713 Load rules in global container
authorDuarte Meneses <duarte.meneses@sonarsource.com>
Mon, 27 Jul 2015 14:25:31 +0000 (16:25 +0200)
committerDuarte Meneses <duarte.meneses@sonarsource.com>
Tue, 28 Jul 2015 12:54:10 +0000 (14:54 +0200)
50 files changed:
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java
plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java
plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/XooRulesDefinitionTest.java
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/Rule.java [new file with mode: 0644]
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/RulesSearchResult.java [new file with mode: 0644]
sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/RulesSearchResultTest.java [new file with mode: 0644]
sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/RulesSearchTest/empty.json [new file with mode: 0644]
sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/RulesSearchTest/expected.json [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java
sonar-batch/src/main/java/org/sonar/batch/cpd/CpdComponents.java
sonar-batch/src/main/java/org/sonar/batch/issue/ModuleIssues.java
sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java
sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java
sonar-batch/src/main/java/org/sonar/batch/rule/DefaultRulesLoader.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/rule/RuleFinderCompatibility.java
sonar-batch/src/main/java/org/sonar/batch/rule/RulesLoader.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
sonar-batch/src/main/java/org/sonar/batch/scan/ProjectWSLoaderProvider.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/report/IssuesReport.java
sonar-batch/src/main/java/org/sonar/batch/scan/report/IssuesReportBuilder.java
sonar-batch/src/main/java/org/sonar/batch/scan/report/JSONReport.java
sonar-batch/src/main/java/org/sonar/batch/scan/report/ReportRuleKey.java
sonar-batch/src/main/java/org/sonar/batch/scan/report/ReportSummary.java
sonar-batch/src/main/java/org/sonar/batch/scan/report/ResourceReport.java
sonar-batch/src/main/java/org/sonar/batch/scan/report/RuleNameProvider.java
sonar-batch/src/main/java/org/sonar/batch/scan/report/RuleReport.java
sonar-batch/src/test/java/org/sonar/batch/issue/ModuleIssuesTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/deprecated/DeprecatedApiMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/ProjectBuilderMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/fs/RandomFsAccessMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/ChecksMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesOnDirMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/MultilineIssuesMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/preview/EmptyFileTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/preview/IncrementalModeMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/preview/PreviewAndReportsMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/rule/DefaultRulesLoaderTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/rule/RuleFinderCompatibilityTest.java
sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/scan/report/JSONReportTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/report/RuleNameProviderTest.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/Rules.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultActiveRule.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/DefaultRules.java
sonar-plugin-api/src/test/java/org/sonar/api/batch/rule/internal/ActiveRulesBuilderTest.java

index a0f9cfdb4e838d14e0599aba56f618d41ba7c2eb..fdd9505fac0a02f648d739dee8fd42cdbaa62e8c 100644 (file)
@@ -105,4 +105,5 @@ public class XooPlugin extends SonarPlugin {
       XooProjectBuilder.class,
       XooPostJob.class);
   }
+
 }
index b7d826a03a801003667a72f829e6642bbaa484f4..74f4e2a7fee8fb99b48a06b31669cd49f5bbafb8 100644 (file)
@@ -76,7 +76,13 @@ public class XooRulesDefinition implements RulesDefinition {
 
     repo.createRule(CustomMessageSensor.RULE_KEY).setName("Issue With Custom Message")
       .setHtmlDescription("Generate an issue on each file with a custom message");
+    
+    repo.createRule(RandomAccessSensor.RULE_KEY).setName("One Issue Per File with Random Access")
+      .setHtmlDescription("This issue is generated on each file");
 
+    repo.createRule(DeprecatedResourceApiSensor.RULE_KEY).setName("Issue created using deprecated API")
+    .setHtmlDescription("Issue created using deprecated API");
+    
     repo.done();
 
   }
index 556ce27aa8815e53dee949a9987b453224b97d23..30e8a45261d4ff27756e3b1cd4bda787b05c44f7 100644 (file)
@@ -37,7 +37,7 @@ public class XooRulesDefinitionTest {
     assertThat(repo).isNotNull();
     assertThat(repo.name()).isEqualTo("Xoo");
     assertThat(repo.language()).isEqualTo("xoo");
-    assertThat(repo.rules()).hasSize(8);
+    assertThat(repo.rules()).hasSize(10);
 
     RulesDefinition.Rule rule = repo.rule(OneIssuePerLineSensor.RULE_KEY);
     assertThat(rule.name()).isNotEmpty();
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/Rule.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/Rule.java
new file mode 100644 (file)
index 0000000..e1574f1
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.batch.protocol.input;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+public class Rule {
+  private final String key;
+  private final String repo;
+  private final String internalKey;
+  private final String name;
+  private final String severity;
+  private final String lang;
+
+  public Rule(String ruleKey, String repositoryKey, String internalKey, String name, @Nullable String severity, @Nullable String language) {
+    this.key = ruleKey;
+    this.repo = repositoryKey;
+    this.internalKey = internalKey;
+    this.name = name;
+    this.severity = severity;
+    this.lang = language;
+  }
+
+  public String ruleKey() {
+    return key;
+  }
+  
+  public String repositoryKey() {
+    return repo;
+  }
+  
+  public String internalKey() {
+    return internalKey;
+  }
+
+  public String name() {
+    return name;
+  }
+
+  /**
+   * Is null on manual rules
+   */
+  @CheckForNull
+  public String severity() {
+    return severity;
+  }
+
+  /**
+   * Is null on manual rules
+   */
+  @CheckForNull
+  public String language() {
+    return lang;
+  }
+
+}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/RulesSearchResult.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/RulesSearchResult.java
new file mode 100644 (file)
index 0000000..91dccb1
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.batch.protocol.input;
+
+import java.util.List;
+
+import org.sonar.batch.protocol.GsonHelper;
+
+public class RulesSearchResult {
+  List<Rule> rules;
+
+  public List<Rule> getRules() {
+    return rules;
+  }
+
+  public void setRules(List<Rule> rules) {
+    this.rules = rules;
+  }
+
+  public String toJson() {
+    return GsonHelper.create().toJson(this);
+  }
+
+  public static RulesSearchResult fromJson(String json) {
+    return GsonHelper.create().fromJson(json, RulesSearchResult.class);
+  }
+
+}
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/RulesSearchResultTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/RulesSearchResultTest.java
new file mode 100644 (file)
index 0000000..0455cc2
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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.batch.protocol.input;
+
+import org.apache.commons.io.IOUtils;
+
+import java.io.IOException;
+import java.net.URL;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.sonar.test.JsonAssert;
+import org.assertj.core.util.Lists;
+import org.junit.Test;
+
+public class RulesSearchResultTest {
+  @Test
+  public void testJsonParsing() {
+    Rule rule1 = new Rule("squid:S1194", "squid", "S1194", "\"java.lang.Error\" should not be extended", "MAJOR", "java");
+    Rule rule2 = new Rule("squid:ObjectFinalizeOverridenCallsSuperFinalizeCheck", "squid", "ObjectFinalizeOverridenCallsSuperFinalizeCheck",
+      "super.finalize() should be called at the end of Object.finalize() implementations", "BLOCKER", "java");
+
+    RulesSearchResult rules = new RulesSearchResult();
+    rules.setRules(Lists.newArrayList(rule1, rule2));
+
+    JsonAssert
+      .assertJson(getClass().getResource("RulesSearchTest/expected.json"))
+      .isSimilarTo(rules.toJson());
+  }
+
+  @Test
+  public void testJsonParsingEmpty() throws IOException {
+    URL resource = getClass().getResource("RulesSearchTest/empty.json");
+    String json = IOUtils.toString(resource);
+    RulesSearchResult result = RulesSearchResult.fromJson(json);
+
+    assertThat(result.getRules()).isEmpty();
+  }
+}
diff --git a/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/RulesSearchTest/empty.json b/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/RulesSearchTest/empty.json
new file mode 100644 (file)
index 0000000..055fe8b
--- /dev/null
@@ -0,0 +1 @@
+{"total":3225,"p":30,"ps":500,"rules":[]}
\ No newline at end of file
diff --git a/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/RulesSearchTest/expected.json b/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/RulesSearchTest/expected.json
new file mode 100644 (file)
index 0000000..89350a7
--- /dev/null
@@ -0,0 +1 @@
+{"total":290,"p":1,"ps":2,"rules":[{"key":"squid:S1194","internalKey":"S1194","repo":"squid","name":"\"java.lang.Error\" should not be extended","severity":"MAJOR","lang":"java"},{"key":"squid:ObjectFinalizeOverridenCallsSuperFinalizeCheck","internalKey":"ObjectFinalizeOverridenCallsSuperFinalizeCheck","repo":"squid","name":"super.finalize() should be called at the end of Object.finalize() implementations","severity":"BLOCKER","lang":"java"}]}
\ No newline at end of file
index cb6f40dafc13d57f5435587f720c9a8b33165704..acf0515fbf5ab15e8f48a9976b96a276018b5869 100644 (file)
@@ -42,8 +42,8 @@ public class BatchComponents {
     // only static stuff
   }
 
-  public static Collection all(GlobalMode analysisMode) {
-    List components = Lists.newArrayList(
+  public static Collection<Object> all(GlobalMode analysisMode) {
+    List<Object> components = Lists.newArrayList(
       DefaultResourceTypes.get(),
       // SCM
       ScmConfiguration.class,
index cea1eabf7bab66f5a6f781582958441e44a1cb01..db806c103c9e4bee1b3fb378931fe88db356d787 100644 (file)
  */
 package org.sonar.batch.bootstrap;
 
+import org.sonar.batch.rule.RulesLoader;
+
+import org.sonar.batch.rule.DefaultRulesLoader;
+import org.sonar.batch.rule.RulesProvider;
+
 import java.util.List;
 import java.util.Map;
 import org.sonar.api.CoreProperties;
@@ -81,6 +86,7 @@ public class GlobalContainer extends ComponentContainer {
     CachesManager.class,
       GlobalMode.class,
       GlobalSettings.class,
+      new RulesProvider(),
       ServerClient.class,
       Logback.class,
       DefaultServer.class,
@@ -94,6 +100,7 @@ public class GlobalContainer extends ComponentContainer {
       new GlobalRepositoriesProvider(),
       UserRepository.class);
     addIfMissing(BatchPluginInstaller.class, PluginInstaller.class);
+    addIfMissing(DefaultRulesLoader.class, RulesLoader.class);
     addIfMissing(DefaultGlobalRepositoriesLoader.class, GlobalRepositoriesLoader.class);
     addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class);
     addIfMissing(DefaultServerIssuesLoader.class, ServerIssuesLoader.class);
index b10f996f20f41374cebf43800cded8d70114304f..197544db075d45c1d61b0e093e412111d59b0e53 100644 (file)
@@ -72,7 +72,7 @@ public class ServerClient {
   }
 
   public URI getURI(String pathStartingWithSlash) {
-    Preconditions.checkArgument(pathStartingWithSlash.startsWith("/"), "Path must start with slash /");
+    Preconditions.checkArgument(pathStartingWithSlash.startsWith("/"), "Path must start with slash /: " + pathStartingWithSlash);
     String path = StringEscapeUtils.escapeHtml(pathStartingWithSlash);
     return URI.create(getURL() + path);
   }
index 7d6a6be2a94f79806231e773c424bbc7e4c28d29..a30c6d0d8323b81577955636464f7271fdb6e2b5 100644 (file)
@@ -20,7 +20,9 @@
 package org.sonar.batch.cpd;
 
 import com.google.common.collect.ImmutableList;
+
 import java.util.List;
+
 import org.sonar.batch.cpd.index.IndexFactory;
 
 public final class CpdComponents {
@@ -28,7 +30,7 @@ public final class CpdComponents {
   private CpdComponents() {
   }
 
-  public static List all() {
+  public static List<? extends Object> all() {
     return ImmutableList.of(
       CpdSensor.class,
       CpdMappings.class,
index 5fad21f090567cc911eff118c2a53002f9282f6f..a27b4c272a3a33e582b405fb7d0b809a821bc22e 100644 (file)
@@ -25,7 +25,6 @@ import org.sonar.api.batch.rule.ActiveRule;
 import org.sonar.api.batch.rule.ActiveRules;
 import org.sonar.api.batch.rule.Rule;
 import org.sonar.api.batch.rule.Rules;
-import org.sonar.api.batch.rule.internal.DefaultActiveRule;
 import org.sonar.api.resources.Project;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.MessageException;
@@ -42,7 +41,7 @@ public class ModuleIssues {
   private final Project project;
   private final IssueFilters filters;
 
-  public ModuleIssues(ActiveRules activeRules, @Nullable Rules rules, IssueCache cache, Project project, IssueFilters filters) {
+  public ModuleIssues(ActiveRules activeRules, Rules rules, IssueCache cache, Project project, IssueFilters filters) {
     this.activeRules = activeRules;
     this.rules = rules;
     this.cache = cache;
@@ -50,17 +49,10 @@ public class ModuleIssues {
     this.filters = filters;
   }
 
-  public ModuleIssues(ActiveRules activeRules, IssueCache cache, Project project, IssueFilters filters) {
-    this(activeRules, null, cache, project, filters);
-  }
-
   public boolean initAndAddIssue(DefaultIssue issue) {
     RuleKey ruleKey = issue.ruleKey();
-    Rule rule = null;
-    if (rules != null) {
-      rule = rules.find(ruleKey);
-      validateRule(issue, rule);
-    }
+    Rule rule = rules.find(ruleKey);
+    validateRule(issue, rule);
     ActiveRule activeRule = activeRules.find(ruleKey);
     if (activeRule == null) {
       // rule does not exist or is not enabled -> ignore the issue
@@ -86,7 +78,7 @@ public class ModuleIssues {
 
   private void updateIssue(DefaultIssue issue, @Nullable Rule rule, ActiveRule activeRule) {
     if (Strings.isNullOrEmpty(issue.message())) {
-      issue.setMessage(((DefaultActiveRule) activeRule).name());
+      issue.setMessage(rule.name());
     }
     if (project != null) {
       issue.setCreationDate(project.getAnalysisDate());
index 370c3f32ca92094a4e634f9bd69f0f3d16ce6d6b..6cf1c15157dbef223d2032fba6309f98bc870406 100644 (file)
  */
 package org.sonar.batch.mediumtest;
 
+import org.sonar.api.server.rule.RulesDefinition.Repository;
+
+import org.sonar.api.server.rule.RulesDefinition;
+import org.sonar.batch.protocol.input.RulesSearchResult;
+import org.sonar.batch.rule.RulesLoader;
+import org.sonar.batch.protocol.input.Rule;
 import com.google.common.base.Function;
 import com.google.common.io.Files;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.InputStreamReader;
@@ -29,9 +36,11 @@ import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+
 import org.sonar.api.CoreProperties;
 import org.sonar.api.SonarPlugin;
 import org.sonar.api.batch.bootstrap.ProjectReactor;
@@ -78,6 +87,7 @@ public class BatchMediumTester {
     private final FakeServerIssuesLoader serverIssues = new FakeServerIssuesLoader();
     private final FakeServerLineHashesLoader serverLineHashes = new FakeServerLineHashesLoader();
     private final Map<String, String> bootstrapProperties = new HashMap<>();
+    private final FakeRulesLoader rulesLoader = new FakeRulesLoader();
     private LogOutput logOutput = null;
 
     public BatchMediumTester build() {
@@ -116,6 +126,30 @@ public class BatchMediumTester {
       return this;
     }
 
+    public BatchMediumTesterBuilder addRule(Rule rule) {
+      rulesLoader.addRule(rule);
+      return this;
+    }
+
+    public BatchMediumTesterBuilder addRules(List<Rule> rules) {
+      for (Rule r : rules) {
+        rulesLoader.addRule(r);
+      }
+      return this;
+    }
+
+    public BatchMediumTesterBuilder addRules(RulesDefinition rulesDefinition) {
+      RulesDefinition.Context context = new RulesDefinition.Context();
+      rulesDefinition.define(context);
+      List<Repository> repositories = context.repositories();
+      for (Repository repo : repositories) {
+        for (RulesDefinition.Rule rule : repo.rules()) {
+          this.addRule(new Rule(rule.repository().key() + ":" + rule.key(), rule.repository().key(), rule.internalKey(), rule.name(), rule.severity(), repo.language()));
+        }
+      }
+      return this;
+    }
+
     public BatchMediumTesterBuilder addDefaultQProfile(String language, String name) {
       addQProfile(language, name);
       globalRefProvider.globalSettings().put("sonar.profile." + language, name);
@@ -171,6 +205,7 @@ public class BatchMediumTester {
         builder.projectRefProvider,
         builder.serverIssues,
         builder.serverLineHashes,
+        builder.rulesLoader,
         new DefaultDebtModel())
       .setBootstrapProperties(builder.bootstrapProperties)
       .setLogOutput(builder.logOutput)
@@ -223,6 +258,23 @@ public class BatchMediumTester {
     }
   }
 
+  private static class FakeRulesLoader implements RulesLoader {
+    private List<Rule> rules = new LinkedList<>();
+
+    public FakeRulesLoader addRule(Rule rule) {
+      rules.add(rule);
+      return this;
+    }
+
+    @Override
+    public RulesSearchResult load() {
+      RulesSearchResult r = new RulesSearchResult();
+      r.setRules(rules);
+      return r;
+    }
+
+  }
+
   private static class FakeGlobalRepositoriesLoader implements GlobalRepositoriesLoader {
 
     private int metricId = 1;
index 388faf11b6aeeedb377dce127bb34e30c3fd116d..564ce0f365812471c5750f85d2d26dc0cf9f4824 100644 (file)
@@ -64,5 +64,4 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad
       throw MessageException.of("No quality profiles has been found this project, you probably don't have any language plugin suitable for this analysis.");
     }
   }
-
 }
index 532547dc16d827b7c3a1ffaf14376fcf8272ae40..5bb0a4a86bd74d80d480a27df9f4ad8cd21cd750 100644 (file)
@@ -44,7 +44,7 @@ public class ActiveRulesProvider extends ProviderAdapter {
     return singleton;
   }
 
-  private ActiveRules load(ProjectRepositories ref) {
+  private static ActiveRules load(ProjectRepositories ref) {
     ActiveRulesBuilder builder = new ActiveRulesBuilder();
     for (ActiveRule activeRule : ref.activeRules()) {
       NewActiveRule newActiveRule = builder.create(RuleKey.of(activeRule.repositoryKey(), activeRule.ruleKey()));
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/DefaultRulesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/rule/DefaultRulesLoader.java
new file mode 100644 (file)
index 0000000..9ab9c17
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.batch.rule;
+
+import org.sonar.batch.protocol.input.Rule;
+
+import org.sonar.batch.protocol.input.RulesSearchResult;
+import org.sonar.batch.bootstrap.WSLoader;
+
+public class DefaultRulesLoader implements RulesLoader {
+  private static final String RULES_SEARCH_URL = "/api/rules/search?ps=500&f=repo,name,internalKey,severity,lang";
+
+  private final WSLoader wsLoader;
+
+  public DefaultRulesLoader(WSLoader wsLoader) {
+    this.wsLoader = wsLoader;
+  }
+
+  @Override
+  public RulesSearchResult load() {
+
+    RulesSearchResult rules = RulesSearchResult.fromJson(wsLoader.loadString(getUrl(1)));
+
+    for (int i = 2; i < 100; i++) {
+      RulesSearchResult moreRules = RulesSearchResult.fromJson(wsLoader.loadString(getUrl(i)));
+      if (moreRules.getRules().isEmpty()) {
+        break;
+      }
+      rules.getRules().addAll(moreRules.getRules());
+    }
+    return rules;
+  }
+
+  private String getUrl(int page) {
+    return RULES_SEARCH_URL + "&p=" + page;
+  }
+}
index 6dab1413350f6c57e13fc9518275cda0a2ea642e..fc0f28ed66eb90e0c49912f0c0143cebf21c15d9 100644 (file)
  */
 package org.sonar.batch.rule;
 
+import org.sonar.api.batch.rule.Rules;
+
 import com.google.common.base.Function;
 import com.google.common.collect.Collections2;
 import org.apache.commons.lang.builder.ReflectionToStringBuilder;
 import org.apache.commons.lang.builder.ToStringStyle;
-import org.sonar.api.batch.rule.ActiveRule;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.internal.DefaultActiveRule;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RuleFinder;
@@ -46,10 +45,10 @@ import java.util.Collections;
  */
 public class RuleFinderCompatibility implements RuleFinder {
 
-  private final ActiveRules activeRules;
+  private final Rules rules;
 
-  public RuleFinderCompatibility(ActiveRules activeRules) {
-    this.activeRules = activeRules;
+  public RuleFinderCompatibility(Rules rules) {
+    this.rules = rules;
   }
 
   @Override
@@ -64,7 +63,7 @@ public class RuleFinderCompatibility implements RuleFinder {
 
   @Override
   public Rule findByKey(RuleKey key) {
-    return toRule(activeRules.find(key));
+    return toRule(rules.find(key));
   }
 
   @Override
@@ -96,28 +95,27 @@ public class RuleFinderCompatibility implements RuleFinder {
   }
 
   private Collection<Rule> byRepository(RuleQuery query) {
-    return Collections2.transform(activeRules.findByRepository(query.getRepositoryKey()), new Function<ActiveRule, Rule>() {
+    return Collections2.transform(rules.findByRepository(query.getRepositoryKey()), new Function<org.sonar.api.batch.rule.Rule, Rule>() {
       @Override
-      public Rule apply(@Nonnull ActiveRule input) {
+      public Rule apply(@Nonnull org.sonar.api.batch.rule.Rule input) {
         return toRule(input);
       }
     });
   }
 
   private Collection<Rule> byKey(RuleQuery query) {
-    Rule rule = toRule(activeRules.find(RuleKey.of(query.getRepositoryKey(), query.getKey())));
+    Rule rule = toRule(rules.find(RuleKey.of(query.getRepositoryKey(), query.getKey())));
     return rule != null ? Arrays.asList(rule) : Collections.<Rule>emptyList();
   }
 
   private Collection<Rule> byInternalKey(RuleQuery query) {
-    Rule rule = toRule(activeRules.findByInternalKey(query.getRepositoryKey(), query.getConfigKey()));
+    Rule rule = toRule(rules.findByInternalKey(query.getRepositoryKey(), query.getConfigKey()));
     return rule != null ? Arrays.asList(rule) : Collections.<Rule>emptyList();
   }
 
   @CheckForNull
-  private Rule toRule(@Nullable ActiveRule rule) {
-    DefaultActiveRule ar = (DefaultActiveRule) rule;
-    return ar == null ? null : Rule.create(ar.ruleKey().repository(), ar.ruleKey().rule()).setName(ar.name()).setConfigKey(ar.internalKey()).setLanguage(ar.language());
+  private static Rule toRule(@Nullable org.sonar.api.batch.rule.Rule ar) {
+    return ar == null ? null : Rule.create(ar.key().repository(), ar.key().rule()).setName(ar.name()).setConfigKey(ar.internalKey());
   }
 
 }
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/RulesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/rule/RulesLoader.java
new file mode 100644 (file)
index 0000000..84a937b
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.batch.rule;
+
+import org.sonar.batch.protocol.input.RulesSearchResult;
+
+public interface RulesLoader {
+  RulesSearchResult load();
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java b/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProvider.java
new file mode 100644 (file)
index 0000000..c864489
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.batch.rule;
+
+import org.picocontainer.injectors.ProviderAdapter;
+
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.batch.rule.internal.RulesBuilder;
+import org.sonar.api.batch.rule.internal.NewRule;
+import org.sonar.batch.protocol.input.Rule;
+import org.sonar.api.batch.rule.Rules;
+
+public class RulesProvider extends ProviderAdapter {
+  private Rules singleton = null;
+
+  public Rules provide(RulesLoader ref) {
+    if (singleton == null) {
+      singleton = load(ref);
+    }
+    return singleton;
+  }
+
+  private static Rules load(RulesLoader ref) {
+    RulesBuilder builder = new RulesBuilder();
+
+    for (Rule inputRule : ref.load().getRules()) {
+      NewRule newRule = builder.add(RuleKey.parse(inputRule.ruleKey()));
+      newRule.setName(inputRule.name());
+      newRule.setSeverity(inputRule.severity());
+      newRule.setInternalKey(inputRule.internalKey());
+    }
+
+    return builder.build();
+  }
+
+}
index 1e0b5d4571bb449917d14c2802f5f5d2f33b1613..30bd5a2ff26093ed6b344949d25ff727637f369a 100644 (file)
@@ -132,7 +132,7 @@ public class ProjectScanContainer extends ComponentContainer {
       ProjectExclusions.class,
       ProjectReactorValidator.class,
       new ProjectRepositoriesProvider(),
-      new WSLoaderProjectProvider(),
+      new ProjectWSLoaderProvider(),
       DefaultResourceCreationLock.class,
       CodeColorizers.class,
       MetricProvider.class,
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectWSLoaderProvider.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectWSLoaderProvider.java
new file mode 100644 (file)
index 0000000..e3caa1d
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.batch.scan;
+
+import org.picocontainer.injectors.ProviderAdapter;
+
+import java.util.Map;
+
+import org.sonar.batch.bootstrap.AnalysisProperties;
+import org.sonar.batch.bootstrap.ServerClient;
+import org.sonar.batch.bootstrap.WSLoader;
+import org.sonar.home.cache.PersistentCache;
+import org.sonar.api.batch.AnalysisMode;
+import org.sonar.batch.bootstrap.WSLoader.LoadStrategy;
+
+public class ProjectWSLoaderProvider extends ProviderAdapter {
+  private WSLoader wsLoader;
+
+  public WSLoader provide(AnalysisProperties props, AnalysisMode mode, PersistentCache cache, ServerClient client) {
+    if (wsLoader == null) {
+      // recreate cache directory if needed for this analysis
+      cache.reconfigure();
+      wsLoader = new WSLoader(isCacheEnabled(props.properties(), mode.isPreview()), cache, client);
+      wsLoader.setStrategy(getStrategy(mode));
+    }
+    return wsLoader;
+  }
+
+  private static LoadStrategy getStrategy(AnalysisMode mode) {
+    if (mode.isQuick()) {
+      return LoadStrategy.CACHE_FIRST;
+    }
+
+    return LoadStrategy.SERVER_FIRST;
+  }
+
+  private static boolean isCacheEnabled(Map<String, String> props, boolean isPreview) {
+    String enableOffline = props.get("sonar.enableOffline");
+    return isPreview && "true".equals(enableOffline);
+  }
+}
index c087219e1f28c10537ec18ff1722f54b3cb51b01..1f2b551ef2f3dd673c3262e5580ced22333936d8 100644 (file)
  */
 package org.sonar.batch.scan.report;
 
+import org.sonar.api.batch.rule.Rule;
+
 import com.google.common.collect.Maps;
 import org.sonar.api.issue.Issue;
-import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RulePriority;
 import org.sonar.batch.index.BatchComponent;
 
index 43e423e7fa7fc640b73a28a57e05053f91264cba..9be4093233a7b126539922051cea4ffcc96432fe 100644 (file)
@@ -19,6 +19,9 @@
  */
 package org.sonar.batch.scan.report;
 
+import org.sonar.api.batch.rule.Rule;
+
+import org.sonar.api.batch.rule.Rules;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.BatchSide;
@@ -26,8 +29,6 @@ import org.sonar.api.issue.Issue;
 import org.sonar.core.issue.DefaultIssue;
 import org.sonar.api.resources.Project;
 import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
 import org.sonar.api.rules.RulePriority;
 import org.sonar.batch.DefaultProjectTree;
 import org.sonar.batch.index.BatchComponent;
@@ -43,14 +44,14 @@ public class IssuesReportBuilder {
   private static final Logger LOG = LoggerFactory.getLogger(IssuesReportBuilder.class);
 
   private final IssueCache issueCache;
-  private final RuleFinder ruleFinder;
+  private final Rules rules;
   private final BatchComponentCache resourceCache;
   private final DefaultProjectTree projectTree;
   private final InputPathCache inputPathCache;
 
-  public IssuesReportBuilder(IssueCache issueCache, RuleFinder ruleFinder, BatchComponentCache resourceCache, DefaultProjectTree projectTree, InputPathCache inputPathCache) {
+  public IssuesReportBuilder(IssueCache issueCache, Rules rules, BatchComponentCache resourceCache, DefaultProjectTree projectTree, InputPathCache inputPathCache) {
     this.issueCache = issueCache;
-    this.ruleFinder = ruleFinder;
+    this.rules = rules;
     this.resourceCache = resourceCache;
     this.projectTree = projectTree;
     this.inputPathCache = inputPathCache;
@@ -98,8 +99,7 @@ public class IssuesReportBuilder {
 
   @CheckForNull
   private Rule findRule(Issue issue) {
-    RuleKey ruleKey = issue.ruleKey();
-    return ruleFinder.findByKey(ruleKey);
+    return rules.find(issue.ruleKey());
   }
 
 }
index b13b5468d67db40069976f09570ea39b590e66ef..7dd9db0d18d52a3560cf695c0d773c106816b03f 100644 (file)
@@ -19,6 +19,9 @@
  */
 package org.sonar.batch.scan.report;
 
+import org.sonar.api.batch.rule.Rule;
+
+import org.sonar.api.batch.rule.Rules;
 import com.google.common.annotations.VisibleForTesting;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
@@ -31,8 +34,6 @@ import org.sonar.api.batch.fs.InputDir;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.internal.DefaultInputDir;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.internal.DefaultActiveRule;
 import org.sonar.api.config.Settings;
 import org.sonar.core.issue.DefaultIssue;
 import org.sonar.api.platform.Server;
@@ -72,18 +73,18 @@ public class JSONReport implements Reporter {
   private final Settings settings;
   private final FileSystem fileSystem;
   private final Server server;
-  private final ActiveRules activeRules;
+  private final Rules rules;
   private final IssueCache issueCache;
   private final InputPathCache fileCache;
   private final Project rootModule;
   private final UserRepository userRepository;
 
-  public JSONReport(Settings settings, FileSystem fileSystem, Server server, ActiveRules activeRules, IssueCache issueCache,
+  public JSONReport(Settings settings, FileSystem fileSystem, Server server, Rules rules, IssueCache issueCache,
     Project rootModule, InputPathCache fileCache, UserRepository userRepository) {
     this.settings = settings;
     this.fileSystem = fileSystem;
     this.server = server;
-    this.activeRules = activeRules;
+    this.rules = rules;
     this.issueCache = issueCache;
     this.rootModule = rootModule;
     this.fileCache = fileCache;
@@ -214,7 +215,7 @@ public class JSONReport implements Reporter {
     json.endArray();
   }
 
-  private void writeUsers(JsonWriter json, Collection<BatchInput.User> users) throws IOException {
+  private static void writeUsers(JsonWriter json, Collection<BatchInput.User> users) throws IOException {
     json.name("users").beginArray();
     for (BatchInput.User user : users) {
       json
@@ -227,7 +228,7 @@ public class JSONReport implements Reporter {
   }
 
   private String getRuleName(RuleKey ruleKey) {
-    DefaultActiveRule rule = (DefaultActiveRule) activeRules.find(ruleKey);
+    Rule rule = rules.find(ruleKey);
     return rule != null ? rule.name() : null;
   }
 
index 99549c2ac1d36d309ffb988f0c872093e962b1cc..0373e62c50434bb739bbed97dea9d38dd91b3f58 100644 (file)
  */
 package org.sonar.batch.scan.report;
 
+import org.sonar.api.batch.rule.Rule;
+
 import org.apache.commons.lang.ObjectUtils;
 import org.apache.commons.lang.builder.ToStringBuilder;
-import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RulePriority;
 
 /**
@@ -68,7 +69,7 @@ public class ReportRuleKey implements Comparable<ReportRuleKey> {
   @Override
   public int compareTo(ReportRuleKey o) {
     if (severity == o.getSeverity()) {
-      return getRule().ruleKey().toString().compareTo(o.getRule().ruleKey().toString());
+      return getRule().key().toString().compareTo(o.getRule().key().toString());
     }
     return o.getSeverity().compareTo(severity);
   }
index 18e964fa262b1fa47f2ffe421a6ea8f06d66ef16..680b4f086ecd18882784f2baeb5ae6816a8e7a2d 100644 (file)
  */
 package org.sonar.batch.scan.report;
 
+import org.sonar.api.batch.rule.Rule;
+
 import com.google.common.collect.Maps;
 import org.sonar.api.issue.Issue;
-import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RulePriority;
 
 import java.util.ArrayList;
@@ -49,12 +50,12 @@ public class ReportSummary {
     initMaps(reportRuleKey);
     ruleReportByRuleKey.get(reportRuleKey).getTotal().incrementCountInCurrentAnalysis();
     total.incrementCountInCurrentAnalysis();
-    totalByRuleKey.get(rule.ruleKey().toString()).incrementCountInCurrentAnalysis();
+    totalByRuleKey.get(rule.key().toString()).incrementCountInCurrentAnalysis();
     totalBySeverity.get(severity.toString()).incrementCountInCurrentAnalysis();
     if (issue.isNew()) {
       total.incrementNewIssuesCount();
       ruleReportByRuleKey.get(reportRuleKey).getTotal().incrementNewIssuesCount();
-      totalByRuleKey.get(rule.ruleKey().toString()).incrementNewIssuesCount();
+      totalByRuleKey.get(rule.key().toString()).incrementNewIssuesCount();
       totalBySeverity.get(severity.toString()).incrementNewIssuesCount();
     }
   }
@@ -72,7 +73,7 @@ public class ReportSummary {
     initMaps(reportRuleKey);
     total.incrementResolvedIssuesCount();
     ruleReportByRuleKey.get(reportRuleKey).getTotal().incrementResolvedIssuesCount();
-    totalByRuleKey.get(rule.ruleKey().toString()).incrementResolvedIssuesCount();
+    totalByRuleKey.get(rule.key().toString()).incrementResolvedIssuesCount();
     totalBySeverity.get(severity.toString()).incrementResolvedIssuesCount();
   }
 
@@ -80,8 +81,8 @@ public class ReportSummary {
     if (!ruleReportByRuleKey.containsKey(reportRuleKey)) {
       ruleReportByRuleKey.put(reportRuleKey, new RuleReport(reportRuleKey));
     }
-    if (!totalByRuleKey.containsKey(reportRuleKey.getRule().ruleKey().toString())) {
-      totalByRuleKey.put(reportRuleKey.getRule().ruleKey().toString(), new IssueVariation());
+    if (!totalByRuleKey.containsKey(reportRuleKey.getRule().key().toString())) {
+      totalByRuleKey.put(reportRuleKey.getRule().key().toString(), new IssueVariation());
     }
     if (!totalBySeverity.containsKey(reportRuleKey.getSeverity().toString())) {
       totalBySeverity.put(reportRuleKey.getSeverity().toString(), new IssueVariation());
index 4a4329f908d74229223a1d5c6a85cc0e7d47afa9..2a6135e5c17bc30fc71c9426ae0736d5e237cbeb 100644 (file)
  */
 package org.sonar.batch.scan.report;
 
+import org.sonar.api.batch.rule.Rule;
+
 import com.google.common.collect.Maps;
 import org.sonar.api.issue.Issue;
-import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RulePriority;
 import org.sonar.batch.index.BatchComponent;
 
index 6fa0a7da42eb180ea51f2aaeaee7432aad6276b7..9f61793cb738ae38cddfa3c0586fd217367880df 100644 (file)
  */
 package org.sonar.batch.scan.report;
 
+import org.sonar.api.batch.rule.Rule;
+
+import org.sonar.api.batch.rule.Rules;
 import org.apache.commons.lang.StringEscapeUtils;
 import org.sonar.api.batch.BatchSide;
 import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
 
 import javax.annotation.CheckForNull;
 
 @BatchSide
 public class RuleNameProvider {
-  private RuleFinder ruleFinder;
+  private Rules rules;
 
-  public RuleNameProvider(RuleFinder ruleFinder) {
-    this.ruleFinder = ruleFinder;
+  public RuleNameProvider(Rules rules) {
+    this.rules = rules;
   }
 
   @CheckForNull
   private String nameFromDB(RuleKey ruleKey) {
-    Rule r = ruleFinder.findByKey(ruleKey);
-    return r != null ? r.getName() : null;
+    Rule r = rules.find(ruleKey);
+    return r != null ? r.name() : null;
   }
 
   public String nameForHTML(RuleKey ruleKey) {
@@ -52,8 +53,7 @@ public class RuleNameProvider {
   }
 
   public String nameForHTML(Rule rule) {
-    String name = nameFromDB(RuleKey.of(rule.getRepositoryKey(), rule.getKey()));
-    return StringEscapeUtils.escapeHtml(name != null ? name : rule.getName());
+    return StringEscapeUtils.escapeHtml(rule.name());
   }
 
 }
index 1ddf1b38282238645cb81c26c47d70d9d2cce0ac..16d6b4cf999311e4daeb0ea1ce4424e4a6e58528 100644 (file)
@@ -19,8 +19,9 @@
  */
 package org.sonar.batch.scan.report;
 
+import org.sonar.api.batch.rule.Rule;
+
 import org.apache.commons.lang.builder.ToStringBuilder;
-import org.sonar.api.rules.Rule;
 
 public final class RuleReport {
   private final ReportRuleKey reportRuleKey;
index 3199c7c8f03f4e7812f1f6758b59a0d8dd23035e..a602f1f654939732642d0f3c8ad47be71c5e6587 100644 (file)
@@ -86,7 +86,7 @@ public class ModuleIssuesTest {
 
   @Test
   public void fail_if_rule_has_no_name_and_issue_has_no_message() {
-    ruleBuilder.add(RuleKey.of("squid", "AvoidCycle"));
+    ruleBuilder.add(SQUID_RULE_KEY).setInternalKey(SQUID_RULE_KEY.rule());
     initModuleIssues();
     DefaultIssue issue = new DefaultIssue().setRuleKey(SQUID_RULE_KEY).setMessage("");
 
index 8287a310bfb3cfc459ad45f1244983be544a50dc..f73d1c60f460dc2c07040bc041666798288b3b9c 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.batch.mediumtest.deprecated;
 
+import org.sonar.xoo.rule.XooRulesDefinition;
+
 import com.google.common.collect.ImmutableMap;
 import java.io.File;
 import java.io.IOException;
@@ -42,6 +44,7 @@ public class DeprecatedApiMediumTest {
 
   public BatchMediumTester tester = BatchMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
+    .addRules(new XooRulesDefinition())
     .addDefaultQProfile("xoo", "Sonar Way")
     .activateRule(new ActiveRule("xoo", "DeprecatedResourceApi", null, "One issue per line", "MAJOR", null, "xoo"))
     .build();
@@ -82,9 +85,9 @@ public class DeprecatedApiMediumTest {
       .start();
 
     assertThat(result.issues()).extracting("componentKey", "message", "line").containsOnly(
-      tuple("com.foo.project:src/sample.xoo", "One issue per line", null),
+      tuple("com.foo.project:src/sample.xoo", "Issue created using deprecated API", null),
       tuple("com.foo.project:src/sample.xoo", "Issue created using deprecated API", 1),
-      tuple("com.foo.project:src/package/sample.xoo", "One issue per line", null),
+      tuple("com.foo.project:src/package/sample.xoo", "Issue created using deprecated API", null),
       tuple("com.foo.project:src/package/sample.xoo", "Issue created using deprecated API", 1),
       tuple("com.foo.project:src", "Issue created using deprecated API", null),
       tuple("com.foo.project:src/package", "Issue created using deprecated API", null));
index 05c1efa99de417f53c9ea9d7084f6e46a4041e40..2beb8f133b5a323ec7eae46a52536e87e00dcee4 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.batch.mediumtest.fs;
 
+import org.sonar.xoo.rule.XooRulesDefinition;
+
 import com.google.common.collect.ImmutableMap;
 import org.apache.commons.io.FileUtils;
 import org.junit.After;
@@ -44,6 +46,7 @@ public class ProjectBuilderMediumTest {
 
   public BatchMediumTester tester = BatchMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
+    .addRules(new XooRulesDefinition())
     .addDefaultQProfile("xoo", "Sonar Way")
     .bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_PREVIEW))
     .setPreviousAnalysisDate(new Date())
index 4e75ffc5474b159e9800d3f1ec106de9262b8c07..f27f72c57694c286bf0ed2a0ff291df08994ac4d 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.batch.mediumtest.fs;
 
+import org.sonar.xoo.rule.XooRulesDefinition;
+
 import com.google.common.collect.ImmutableMap;
 import org.apache.commons.io.FileUtils;
 import org.junit.After;
@@ -49,6 +51,7 @@ public class RandomFsAccessMediumTest {
   public BatchMediumTester tester = BatchMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
     .addDefaultQProfile("xoo", "Sonar Way")
+    .addRules(new XooRulesDefinition())
     .activateRule(new ActiveRule("xoo", "RandomAccessIssue", null, "One issue per line", "MAJOR", null, "xoo"))
     .build();
 
index 5cc57070ce595c49e5a3fbcffbe565b887eede2f..7d39819f825e73390477456e60d58b25aa8d36c8 100644 (file)
@@ -19,6 +19,9 @@
  */
 package org.sonar.batch.mediumtest.issues;
 
+import org.sonar.batch.protocol.input.Rule;
+
+import org.sonar.xoo.rule.XooRulesDefinition;
 import com.google.common.collect.ImmutableMap;
 import org.apache.commons.io.FileUtils;
 import org.junit.After;
@@ -42,7 +45,10 @@ public class ChecksMediumTest {
 
   public BatchMediumTester tester = BatchMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
+    .addRules(new XooRulesDefinition())
     .addDefaultQProfile("xoo", "Sonar Way")
+    .addRule(new Rule("xoo:TemplateRule_1234", "xoo", "TemplateRule_1234", "A template rule", "MAJOR", "xoo"))
+    .addRule(new Rule("xoo:TemplateRule_1235", "xoo", "TemplateRule_1235", "Another template rule", "MAJOR", "xoo"))
     .activateRule(new ActiveRule("xoo", "TemplateRule_1234", "TemplateRule", "A template rule", "MAJOR", null, "xoo").addParam("line", "1"))
     .activateRule(new ActiveRule("xoo", "TemplateRule_1235", "TemplateRule", "Another template rule", "MAJOR", null, "xoo").addParam("line", "2"))
     .build();
index 8f46a5d0800c13a7d79e7ed565c1462f4974ecdf..6898c5bfcc94f5c13135c1167baea5790fbb1a75 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.batch.mediumtest.issues;
 
+import org.sonar.xoo.rule.XooRulesDefinition;
+
 import com.google.common.collect.ImmutableMap;
 import org.apache.commons.io.FileUtils;
 import org.junit.After;
@@ -44,6 +46,7 @@ public class IssuesMediumTest {
   public BatchMediumTester tester = BatchMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
     .addDefaultQProfile("xoo", "Sonar Way")
+    .addRules(new XooRulesDefinition())
     .activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", "OneIssuePerLine.internal", "xoo"))
     .build();
 
index 10aef4cb60d4c260b171dcab5187c86eab14804c..2d389a5d8cf8f44116cea790b72b84661e0a2bba 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.batch.mediumtest.issues;
 
+import org.sonar.xoo.rule.XooRulesDefinition;
+
 import com.google.common.collect.ImmutableMap;
 import org.apache.commons.io.FileUtils;
 import org.junit.After;
@@ -43,6 +45,7 @@ public class IssuesOnDirMediumTest {
   public BatchMediumTester tester = BatchMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
     .addDefaultQProfile("xoo", "Sonar Way")
+    .addRules(new XooRulesDefinition())
     .activateRule(new ActiveRule("xoo", "OneIssueOnDirPerFile", null, "One issue per line", "MINOR", "xoo", "xoo"))
     .build();
 
index 749260c423383e1ddb846ba919966fbd44189fff..c07dd6cdbc680d799a71dc0984056a29de2d572b 100644 (file)
  */
 package org.sonar.batch.mediumtest.issues;
 
+import org.sonar.xoo.rule.XooRulesDefinition;
+
+import org.sonar.batch.protocol.input.Rule;
+
 import java.io.File;
+
 import org.apache.commons.io.FileUtils;
 import org.junit.After;
 import org.junit.Before;
@@ -29,7 +34,6 @@ import org.sonar.batch.mediumtest.BatchMediumTester;
 import org.sonar.batch.mediumtest.TaskResult;
 import org.sonar.batch.protocol.input.ActiveRule;
 import org.sonar.xoo.XooPlugin;
-
 import static org.assertj.core.api.Assertions.assertThat;
 
 public class MultilineIssuesMediumTest {
@@ -39,6 +43,8 @@ public class MultilineIssuesMediumTest {
 
   public BatchMediumTester tester = BatchMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
+    .addRules(new XooRulesDefinition())
+    .addRule(new Rule("xoo:MultilineIssue", "xoo", null, "Multinile Issue", "MAJOR", "xoo"))
     .addDefaultQProfile("xoo", "Sonar Way")
     .activateRule(new ActiveRule("xoo", "MultilineIssue", null, "Multinile Issue", "MAJOR", null, "xoo"))
     .build();
index 385023ec1e3d4a65af1a2de81badeaf8110f26e7..3f7be697caf02e021441e67ca1a9dbc199ff8dc6 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.batch.mediumtest.preview;
 
+import org.sonar.xoo.rule.XooRulesDefinition;
+
 import com.google.common.collect.ImmutableMap;
 import org.junit.After;
 import org.junit.Before;
@@ -48,6 +50,7 @@ public class EmptyFileTest {
   public BatchMediumTester tester = BatchMediumTester.builder()
     .bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_PREVIEW))
     .registerPlugin("xoo", new XooPlugin())
+    .addRules(new XooRulesDefinition())
     .addDefaultQProfile("xoo", "Sonar Way")
     .activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", "my/internal/key", "xoo"))
     .setPreviousAnalysisDate(new Date())
index 1f1539388f3d605502c579764b498ba463056257..86697dcea42ede7664c92d38faf9f3523da321e9 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.batch.mediumtest.preview;
 
+import org.sonar.xoo.rule.XooRulesDefinition;
+
 import com.google.common.collect.ImmutableMap;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.io.FileUtils;
@@ -63,6 +65,7 @@ public class IncrementalModeMediumTest {
     .builder()
     .bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_INCREMENTAL))
     .registerPlugin("xoo", new XooPlugin())
+    .addRules(new XooRulesDefinition())
     .addDefaultQProfile("xoo", "Sonar Way")
     .activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", null, "xoo"))
     .activateRule(new ActiveRule("manual", "MyManualIssue", null, "My manual issue", "MAJOR", null, null))
index ab2157d056d0627623cab00a31cdac79ddbf0e26..acf1f5b588b5e1f01bce805de9c030c16b61d952 100644 (file)
  */
 package org.sonar.batch.mediumtest.preview;
 
+import org.sonar.batch.protocol.input.Rule;
+
+import org.sonar.xoo.rule.XooRulesDefinition;
 import com.google.common.collect.ImmutableMap;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.io.FileUtils;
 import org.junit.After;
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.CoreProperties;
@@ -46,10 +48,10 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 public class PreviewAndReportsMediumTest {
 
-  @Rule
+  @org.junit.Rule
   public TemporaryFolder temp = new TemporaryFolder();
 
-  @Rule
+  @org.junit.Rule
   public LogTester logTester = new LogTester();
 
   private static SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
@@ -66,6 +68,8 @@ public class PreviewAndReportsMediumTest {
     .bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_PREVIEW))
     .registerPlugin("xoo", new XooPlugin())
     .addDefaultQProfile("xoo", "Sonar Way")
+    .addRules(new XooRulesDefinition())
+    .addRule(new Rule("manual:MyManualIssue", "manual", "MyManualIssue", "My manual issue", "MAJOR", null))
     .activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", null, "xoo"))
     .activateRule(new ActiveRule("manual", "MyManualIssue", null, "My manual issue", "MAJOR", null, null))
     .setPreviousAnalysisDate(new Date())
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/DefaultRulesLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/DefaultRulesLoaderTest.java
new file mode 100644 (file)
index 0000000..49ecaa0
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.batch.rule;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.LinkedList;
+
+import static org.mockito.Matchers.contains;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.sonar.batch.bootstrap.WSLoader;
+import org.junit.Test;
+import org.sonar.batch.protocol.input.Rule;
+import org.sonar.batch.protocol.input.RulesSearchResult;
+
+public class DefaultRulesLoaderTest {
+  @Test
+  public void testLoadingJson() throws IOException {
+    Rule rule1 = new Rule("squid:S1194", "squid", "S1194", "\"java.lang.Error\" should not be extended", "MAJOR", "java");
+    Rule rule2 = new Rule("squid:ObjectFinalizeOverridenCallsSuperFinalizeCheck", "squid", "ObjectFinalizeOverridenCallsSuperFinalizeCheck",
+      "super.finalize() should be called at the end of Object.finalize() implementations", "BLOCKER", "java");
+
+    // generate json
+    RulesSearchResult rulesSearch = new RulesSearchResult();
+    rulesSearch.setRules(Arrays.asList(rule1, rule2));
+    String json = rulesSearch.toJson();
+
+    RulesSearchResult empty = new RulesSearchResult();
+    empty.setRules(new LinkedList<Rule>());
+    String emptyJson = empty.toJson();
+
+    WSLoader wsLoader = mock(WSLoader.class);
+    when(wsLoader.loadString(contains("p=1"))).thenReturn(json);
+    when(wsLoader.loadString(contains("p=2"))).thenReturn(emptyJson);
+
+    // load
+    RulesLoader loader = new DefaultRulesLoader(wsLoader);
+    RulesSearchResult rules = loader.load();
+
+    assertThat(rules.toJson()).isEqualTo(json);
+  }
+}
index 1c61c091b68b157a84ba557da2d48af40d6bc128..268de8b4e0f0d7279963620b680794c9abb95efb 100644 (file)
  */
 package org.sonar.batch.rule;
 
+import org.sonar.api.batch.rule.internal.RulesBuilder;
+
+import org.sonar.api.batch.rule.Rules;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rules.RuleQuery;
-
 import static org.assertj.core.api.Assertions.assertThat;
 
 public class RuleFinderCompatibilityTest {
@@ -35,20 +35,18 @@ public class RuleFinderCompatibilityTest {
   @Rule
   public ExpectedException thrown = ExpectedException.none();
 
-  private ActiveRules activeRules = new ActiveRulesBuilder()
-    .create(RuleKey.of("repo1", "rule1"))
-    .activate()
-    .create(RuleKey.of("repo1", "rule2"))
-    .setInternalKey("rule2_internal")
-    .activate()
-    .create(RuleKey.of("repo2", "rule1"))
-    .activate()
-    .build();
+  private Rules rules;
   private RuleFinderCompatibility ruleFinder;
 
   @Before
   public void prepare() {
-    ruleFinder = new RuleFinderCompatibility(activeRules);
+    RulesBuilder builder = new RulesBuilder();
+    builder.add(RuleKey.of("repo1", "rule1"));
+    builder.add(RuleKey.of("repo1", "rule2")).setInternalKey("rule2_internal");
+    builder.add(RuleKey.of("repo2", "rule1"));
+    rules = builder.build();
+    
+    ruleFinder = new RuleFinderCompatibility(rules);
   }
 
   @Test
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/RulesProviderTest.java
new file mode 100644 (file)
index 0000000..84e3697
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.batch.rule;
+
+import org.assertj.core.api.Condition;
+
+import org.sonar.api.batch.rule.Rules;
+
+import java.util.Arrays;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.mock;
+import org.sonar.batch.protocol.input.Rule;
+import org.sonar.batch.protocol.input.RulesSearchResult;
+import org.junit.Test;
+
+public class RulesProviderTest {
+  @Test
+  public void testRuleTranslation() {
+    final Rule testRule = new Rule("repo1:key1", "repo1", "key1", "name", "severity", "language");
+
+    RulesSearchResult loadResult = new RulesSearchResult();
+    loadResult.setRules(Arrays.asList(testRule));
+    RulesLoader loader = mock(RulesLoader.class);
+    when(loader.load()).thenReturn(loadResult);
+
+    RulesProvider provider = new RulesProvider();
+    Rules rules = provider.provide(loader);
+
+    assertThat(rules.findAll()).hasSize(1);
+    assertThat(rules.findAll()).are(new Condition<org.sonar.api.batch.rule.Rule>() {
+
+      @Override
+      public boolean matches(org.sonar.api.batch.rule.Rule value) {
+        return value.key().rule().equals(testRule.internalKey()) &&
+          value.internalKey().equals(testRule.internalKey()) &&
+          value.name().equals(testRule.name()) &&
+          value.severity().equals(testRule.severity()) &&
+          value.key().repository().equals(testRule.repositoryKey());
+      }
+    });
+  }
+}
index afc0d4c39aa900bc9cfac7ceb0f2429c4d9b50b6..544b1c065b3141105ec47f77a574989dac89ad3a 100644 (file)
@@ -19,6 +19,9 @@
  */
 package org.sonar.batch.scan.report;
 
+import org.sonar.api.batch.rule.internal.RulesBuilder;
+
+import org.sonar.api.batch.rule.Rules;
 import com.google.common.collect.Lists;
 import com.google.common.io.Resources;
 import org.junit.Before;
@@ -29,8 +32,6 @@ import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.batch.fs.internal.DefaultFileSystem;
 import org.sonar.api.batch.fs.internal.DefaultInputDir;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.rule.ActiveRules;
-import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
 import org.sonar.api.config.Settings;
 import org.sonar.api.issue.Issue;
 import org.sonar.core.issue.DefaultIssue;
@@ -68,7 +69,7 @@ public class JSONReportTest {
   Resource resource = mock(Resource.class);
   DefaultFileSystem fs;
   Server server = mock(Server.class);
-  ActiveRules activeRules = mock(ActiveRules.class);
+  Rules rules = mock(Rules.class);
   Settings settings = new Settings();
   IssueCache issueCache = mock(IssueCache.class);
   private UserRepository userRepository;
@@ -91,10 +92,11 @@ public class JSONReportTest {
     moduleA.setParent(rootModule).setPath("core");
     Project moduleB = new Project("struts-ui");
     moduleB.setParent(rootModule).setPath("ui");
-    activeRules = new ActiveRulesBuilder()
-      .create(RuleKey.of("squid", "AvoidCycles")).setName("Avoid Cycles").activate()
-      .build();
-    jsonReport = new JSONReport(settings, fs, server, activeRules, issueCache, rootModule, fileCache, userRepository);
+
+    RulesBuilder builder = new RulesBuilder();
+    builder.add(RuleKey.of("squid", "AvoidCycles")).setName("Avoid Cycles");
+    rules = builder.build();
+    jsonReport = new JSONReport(settings, fs, server, rules, issueCache, rootModule, fileCache, userRepository);
   }
 
   @Test
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/report/RuleNameProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/report/RuleNameProviderTest.java
new file mode 100644 (file)
index 0000000..fb7e399
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.batch.scan.report;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import static org.mockito.Matchers.any;
+
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.batch.rule.Rule;
+import org.junit.Test;
+import org.junit.Before;
+import org.sonar.api.batch.rule.Rules;
+
+public class RuleNameProviderTest {
+  RuleNameProvider provider;
+  Rules rules;
+  Rule rule;
+  RuleKey ruleKey;
+
+  @Before
+  public void setUp() {
+    ruleKey = mock(RuleKey.class);
+    rule = mock(Rule.class);
+    rules = mock(Rules.class);
+    provider = new RuleNameProvider(rules);
+
+    when(ruleKey.rule()).thenReturn("ruleKey");
+    when(ruleKey.repository()).thenReturn("repoKey");
+
+    when(rule.name()).thenReturn("name");
+    when(rule.key()).thenReturn(ruleKey);
+
+    when(rules.find(any(RuleKey.class))).thenReturn(rule);
+  }
+
+  @Test
+  public void testNameForHTML() {
+    assertThat(provider.nameForHTML(rule)).isEqualTo(rule.name());
+    assertThat(provider.nameForHTML(ruleKey)).isEqualTo(rule.name());
+  }
+
+  @Test
+  public void testNameForJS() {
+    assertThat(provider.nameForJS("repoKey:ruleKey")).isEqualTo(rule.name());
+  }
+
+}
index 3a8bb05e4074f3394cc6db361a30de6ee2985f70..f05b73e8324c11524f29d449bbb6ae3b241fca1b 100644 (file)
@@ -49,4 +49,6 @@ public interface Rules {
    */
   Collection<Rule> findByRepository(String repository);
 
+  Rule findByInternalKey(String repository, String internalKey);
+
 }
index b8b271e481d6d71ec1e5eea4cfc4f8e83161354e..83e6a69f37fc5eb858d913022a6389c8ef99245b 100644 (file)
@@ -30,7 +30,6 @@ import java.util.Map;
 @Immutable
 public class DefaultActiveRule implements ActiveRule {
   private final RuleKey ruleKey;
-  private final String name;
   private final String severity;
   private final String internalKey;
   private final String language;
@@ -39,7 +38,6 @@ public class DefaultActiveRule implements ActiveRule {
 
   DefaultActiveRule(NewActiveRule newActiveRule) {
     this.severity = newActiveRule.severity;
-    this.name = newActiveRule.name;
     this.internalKey = newActiveRule.internalKey;
     this.templateRuleKey = newActiveRule.templateRuleKey;
     this.ruleKey = newActiveRule.ruleKey;
@@ -52,10 +50,6 @@ public class DefaultActiveRule implements ActiveRule {
     return ruleKey;
   }
 
-  public String name() {
-    return name;
-  }
-
   @Override
   public String severity() {
     return severity;
index 3c14387a31c53b9350b0cb75d08d8d794932ab87..1ef36b3e63d7977ee4d68ce800ff7833ba30d041 100644 (file)
  */
 package org.sonar.api.batch.rule.internal;
 
+import org.sonar.api.batch.rule.Rule;
+import com.google.common.collect.ImmutableTable;
+import com.google.common.collect.Table;
 import com.google.common.collect.ImmutableListMultimap;
 import com.google.common.collect.ListMultimap;
 import org.apache.commons.lang.StringUtils;
-import org.sonar.api.batch.rule.Rule;
 import org.sonar.api.batch.rule.Rules;
 import org.sonar.api.rule.RuleKey;
 
@@ -36,14 +38,22 @@ class DefaultRules implements Rules {
 
   // TODO use disk-backed cache (persistit) instead of full in-memory cache ?
   private final ListMultimap<String, Rule> rulesByRepository;
+  private final Table<String, String, Rule> rulesByRepositoryAndInternalKey;
 
   DefaultRules(Collection<NewRule> newRules) {
     ImmutableListMultimap.Builder<String, Rule> builder = ImmutableListMultimap.builder();
+    ImmutableTable.Builder<String, String, Rule> tableBuilder = ImmutableTable.builder();
+
     for (NewRule newRule : newRules) {
       DefaultRule r = new DefaultRule(newRule);
       builder.put(r.key().repository(), r);
+      if (r.internalKey() != null) {
+        tableBuilder.put(r.key().repository(), r.internalKey(), r);
+      }
     }
+
     rulesByRepository = builder.build();
+    rulesByRepositoryAndInternalKey = tableBuilder.build();
   }
 
   @Override
@@ -66,4 +76,9 @@ class DefaultRules implements Rules {
   public Collection<Rule> findByRepository(String repository) {
     return rulesByRepository.get(repository);
   }
+
+  @Override
+  public Rule findByInternalKey(String repository, String internalKey) {
+    return rulesByRepositoryAndInternalKey.get(repository, internalKey);
+  }
 }
index 726395963abbc4798f2079372429b14908c10783..14382e8826594008835f441bc670e26cfd7bef16 100644 (file)
@@ -63,7 +63,6 @@ public class ActiveRulesBuilderTest {
     ActiveRule squid1 = activeRules.find(RuleKey.of("squid", "S0001"));
     assertThat(squid1.ruleKey().repository()).isEqualTo("squid");
     assertThat(squid1.ruleKey().rule()).isEqualTo("S0001");
-    assertThat(((DefaultActiveRule) squid1).name()).isEqualTo("My Rule");
     assertThat(squid1.severity()).isEqualTo(Severity.CRITICAL);
     assertThat(squid1.internalKey()).isEqualTo("__S0001__");
     assertThat(squid1.params()).hasSize(1);