diff options
author | Simon Brandhof <simon.brandhof@gmail.com> | 2013-05-03 18:58:14 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@gmail.com> | 2013-05-03 18:58:14 +0200 |
commit | d36537ad6bb829c4a3fb19ac4de1fccd77aa1f64 (patch) | |
tree | 8926e7b56715a00be507dd1c232d88766e9fe829 | |
parent | 38f5db2f92216e23a3b477d5d8872c5165e45248 (diff) | |
download | sonarqube-d36537ad6bb829c4a3fb19ac4de1fccd77aa1f64.tar.gz sonarqube-d36537ad6bb829c4a3fb19ac4de1fccd77aa1f64.zip |
SONAR-3755 refactor issue search
18 files changed, 238 insertions, 209 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueFinder.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueFinder.java index 7ba13797017..735225e461e 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueFinder.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueFinder.java @@ -23,10 +23,10 @@ package org.sonar.api.issue; import org.sonar.api.ServerComponent; import org.sonar.api.component.Component; import org.sonar.api.rules.Rule; +import org.sonar.api.utils.Paging; import javax.annotation.CheckForNull; import javax.annotation.Nullable; - import java.util.Collection; import java.util.List; @@ -62,10 +62,4 @@ public interface IssueFinder extends ServerComponent { @CheckForNull Issue findByKey(String key /* TODO @Nullable Integer currentUserId */); - - /* - Map<RuleKey, Rule> rules(Collection<Issue> issues); - - Map<String, Component> components(Collection<Issue> issues); -*/ } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java index 796a6d42df7..d3fedd09ac7 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java @@ -157,7 +157,7 @@ public class IssueQuery { public static class Builder { private enum Sort { - created, updated, closed, assignee; + created, updated, closed, assignee } private static final int DEFAULT_PAGE_SIZE = 100; @@ -265,15 +265,15 @@ public class IssueQuery { } public Builder pageSize(@Nullable Integer i) { - Preconditions.checkArgument(i == null || i.intValue() > 0, "Page size must be greater than 0 (got " + i + ")"); - Preconditions.checkArgument(i == null || i.intValue() < MAX_PAGE_SIZE, "Page size must be less than " + MAX_PAGE_SIZE + " (got " + i + ")"); + Preconditions.checkArgument(i == null || i > 0, "Page size must be greater than 0 (got " + i + ")"); + Preconditions.checkArgument(i == null || i < MAX_PAGE_SIZE, "Page size must be less than " + MAX_PAGE_SIZE + " (got " + i + ")"); this.pageSize = (i == null ? DEFAULT_PAGE_SIZE : i.intValue()); return this; } public Builder pageIndex(@Nullable Integer i) { - Preconditions.checkArgument(i == null || i.intValue() > 0, "Page index must be greater than 0 (got " + i + ")"); - this.pageIndex = (i == null ? DEFAULT_PAGE_INDEX : i.intValue()); + Preconditions.checkArgument(i == null || i > 0, "Page index must be greater than 0 (got " + i + ")"); + this.pageIndex = (i == null ? DEFAULT_PAGE_INDEX : i); return this; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/JRubyIssues.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/WebIssues.java index a56d44340e4..67932f0fe59 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/JRubyIssues.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/WebIssues.java @@ -31,7 +31,7 @@ import java.util.Map; * * @since 3.6 */ -public interface JRubyIssues extends ServerComponent { +public interface WebIssues extends ServerComponent { /** * Search for issues. diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Paging.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/Paging.java index 867cec866ca..0fc31c4b18a 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Paging.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/Paging.java @@ -18,10 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.api.issue; +package org.sonar.api.utils; /** - * TODO move outside this package * @since 3.6 */ public class Paging { @@ -30,20 +29,29 @@ public class Paging { private final int pageIndex; private final int total; - public Paging(int pageSize, int pageIndex, int total) { + private Paging(int pageSize, int pageIndex, int total) { this.pageSize = pageSize; this.pageIndex = pageIndex; this.total = total; } + /** + * Page index, starting with 1. + */ public int pageIndex() { return pageIndex; } + /** + * Maximum number of items per page. It is greater than 0. + */ public int pageSize() { return pageSize; } + /** + * Total number of items. It is greater than or equal 0. + */ public int total() { return total; } @@ -52,6 +60,9 @@ public class Paging { return (pageIndex - 1) * pageSize; } + /** + * Number of pages. It is greater than or equal 0. + */ public int pages() { int p = (total / pageSize); if ((total % pageSize) > 0) { @@ -59,4 +70,17 @@ public class Paging { } return p; } + + public static Paging create(int pageSize, int pageIndex, int totalItems) { + if (pageSize<1) { + throw new IllegalArgumentException("Page size must be strictly positive. Got " + pageSize); + } + if (pageIndex<1) { + throw new IllegalArgumentException("Page index must be strictly positive. Got " + pageIndex); + } + if (totalItems<0) { + throw new IllegalArgumentException("Total items must be positive. Got " + totalItems); + } + return new Paging(pageSize, pageIndex, totalItems); + } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/issue/PagingTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/issue/PagingTest.java deleted file mode 100644 index ca9dbf25df2..00000000000 --- a/sonar-plugin-api/src/test/java/org/sonar/api/issue/PagingTest.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.issue; - -import org.junit.Test; - -import static org.fest.assertions.Assertions.assertThat; - -public class PagingTest { - - @Test - public void test_pagination(){ - Paging paging = new Paging(5, 1, 20); - - assertThat(paging.pageSize()).isEqualTo(5); - assertThat(paging.pageIndex()).isEqualTo(1); - assertThat(paging.total()).isEqualTo(20); - - assertThat(paging.offset()).isEqualTo(0); - assertThat(paging.pages()).isEqualTo(4); - } - - @Test - public void test_offset(){ - assertThat(new Paging(5, 1, 20).offset()).isEqualTo(0); - assertThat(new Paging(5, 2, 20).offset()).isEqualTo(5); - } - - @Test - public void test_number_of_pages(){ - assertThat(new Paging(5, 2, 20).pages()).isEqualTo(4); - assertThat(new Paging(5, 2, 21).pages()).isEqualTo(5); - assertThat(new Paging(5, 2, 25).pages()).isEqualTo(5); - assertThat(new Paging(5, 2, 26).pages()).isEqualTo(6); - } -} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/PagingTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/PagingTest.java new file mode 100644 index 00000000000..0d28a7b5ccc --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/PagingTest.java @@ -0,0 +1,85 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.utils; + +import org.junit.Test; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; + +public class PagingTest { + + @Test + public void test_pagination() { + Paging paging = Paging.create(5, 1, 20); + + assertThat(paging.pageSize()).isEqualTo(5); + assertThat(paging.pageIndex()).isEqualTo(1); + assertThat(paging.total()).isEqualTo(20); + + assertThat(paging.offset()).isEqualTo(0); + assertThat(paging.pages()).isEqualTo(4); + } + + @Test + public void test_offset() { + assertThat(Paging.create(5, 1, 20).offset()).isEqualTo(0); + assertThat(Paging.create(5, 2, 20).offset()).isEqualTo(5); + } + + @Test + public void test_number_of_pages() { + assertThat(Paging.create(5, 2, 20).pages()).isEqualTo(4); + assertThat(Paging.create(5, 2, 21).pages()).isEqualTo(5); + assertThat(Paging.create(5, 2, 25).pages()).isEqualTo(5); + assertThat(Paging.create(5, 2, 26).pages()).isEqualTo(6); + } + + @Test + public void page_size_should_be_strictly_positive() throws Exception { + try { + Paging.create(0, 5, 5); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Page size must be strictly positive. Got 0"); + } + } + + @Test + public void page_index_should_be_strictly_positive() throws Exception { + try { + Paging.create(5, 0, 5); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Page index must be strictly positive. Got 0"); + } + } + + @Test + public void total_items_should_be_positive() throws Exception { + try { + Paging.create(5, 5, -1); + fail(); + } catch (IllegalArgumentException e) { + assertThat(e).hasMessage("Total items must be positive. Got -1"); + } + } +} diff --git a/sonar-server/src/main/java/org/sonar/server/issue/JRubyInternalIssues.java b/sonar-server/src/main/java/org/sonar/server/issue/JRubyInternalIssues.java index 2dc008f801f..780c4986ff0 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/JRubyInternalIssues.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/JRubyInternalIssues.java @@ -33,7 +33,8 @@ import java.util.List; import java.util.Map; /** - * All the issue features that are not published to public API + * All the issue features that are not published to public API. + * TODO to be renamed to WebIssuesInternal */ public class JRubyInternalIssues implements ServerComponent { diff --git a/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueFinder.java b/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueFinder.java index 01402ad4217..36d0985bc22 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueFinder.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueFinder.java @@ -20,16 +20,18 @@ package org.sonar.server.issue; import com.google.common.base.Predicate; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Iterables; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.Sets; +import com.google.common.collect.*; import org.apache.ibatis.session.SqlSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.component.Component; -import org.sonar.api.issue.*; +import org.sonar.api.issue.ActionPlan; +import org.sonar.api.issue.Issue; +import org.sonar.api.issue.IssueFinder; +import org.sonar.api.issue.IssueQuery; +import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; +import org.sonar.api.utils.Paging; import org.sonar.core.issue.DefaultIssue; import org.sonar.core.issue.db.ActionPlanIssueDao; import org.sonar.core.issue.db.ActionPlanIssueDto; @@ -41,7 +43,6 @@ import org.sonar.core.rule.DefaultRuleFinder; import org.sonar.core.user.AuthorizationDao; import javax.annotation.Nullable; - import java.util.Collection; import java.util.List; import java.util.Map; @@ -77,14 +78,14 @@ public class ServerIssueFinder implements IssueFinder { SqlSession sqlSession = myBatis.openSession(); try { List<IssueDto> allIssuesDto = issueDao.selectIssueIdsAndComponentsId(query, sqlSession); - Set<Integer> componentIds = getResourceIds(allIssuesDto); + Set<Integer> componentIds = extractResourceIds(allIssuesDto); Set<Integer> authorizedComponentIds = authorizationDao.keepAuthorizedComponentIds(componentIds, currentUserId, role, sqlSession); - List<IssueDto> authorizedIssues = getAuthorizedIssues(allIssuesDto, authorizedComponentIds); - Paging paging = new Paging(query.pageSize(), query.pageIndex(), authorizedIssues.size()); - Set<Long> paginatedAuthorizedIssueIds = getPaginatedAuthorizedIssueIds(authorizedIssues, paging); + List<IssueDto> authorizedIssues = authorized(allIssuesDto, authorizedComponentIds); + Paging paging = Paging.create(query.pageSize(), query.pageIndex(), authorizedIssues.size()); + Set<Long> pagedAuthorizedIssueIds = pagedAuthorizedIssueIds(authorizedIssues, paging); - Collection<IssueDto> dtos = issueDao.selectByIds(paginatedAuthorizedIssueIds, sqlSession); - Set<Integer> ruleIds = Sets.newLinkedHashSet(); + Collection<IssueDto> dtos = issueDao.selectByIds(pagedAuthorizedIssueIds, sqlSession); + Set<Integer> ruleIds = Sets.newHashSet(); List<Issue> issues = newArrayList(); List<Long> issueIds = newArrayList(); Map<Long, Issue> issuesById = newHashMap(); @@ -102,23 +103,26 @@ public class ServerIssueFinder implements IssueFinder { ListMultimap<Issue, ActionPlan> actionPlansByIssueKey = createActionPlansByIssue(actionPlanIssueDtos, issuesById); setActionPlans(issues, actionPlansByIssueKey); - return new DefaultResults(issues, getRulesByIssue(issues, ruleIds), getComponentsByIssue(issues, componentIds), actionPlansByIssueKey, + return new DefaultResults(issues, + findRules(ruleIds), + findComponents(componentIds), + actionPlansByIssueKey, paging, authorizedIssues.size() != allIssuesDto.size()); } finally { MyBatis.closeQuietly(sqlSession); } } - private Set<Integer> getResourceIds(List<IssueDto> allIssuesDto) { + private Set<Integer> extractResourceIds(List<IssueDto> dtos) { Set<Integer> componentIds = Sets.newLinkedHashSet(); - for (IssueDto issueDto : allIssuesDto) { + for (IssueDto issueDto : dtos) { componentIds.add(issueDto.getResourceId()); } return componentIds; } - private List<IssueDto> getAuthorizedIssues(List<IssueDto> allIssuesDto, final Set<Integer> authorizedComponentIds) { - return newArrayList(Iterables.filter(allIssuesDto, new Predicate<IssueDto>() { + private List<IssueDto> authorized(List<IssueDto> dtos, final Set<Integer> authorizedComponentIds) { + return newArrayList(Iterables.filter(dtos, new Predicate<IssueDto>() { @Override public boolean apply(IssueDto issueDto) { return authorizedComponentIds.contains(issueDto.getResourceId()); @@ -126,7 +130,7 @@ public class ServerIssueFinder implements IssueFinder { })); } - private Set<Long> getPaginatedAuthorizedIssueIds(List<IssueDto> authorizedIssues, Paging paging) { + private Set<Long> pagedAuthorizedIssueIds(List<IssueDto> authorizedIssues, Paging paging) { Set<Long> issueIds = Sets.newLinkedHashSet(); int index = 0; for (IssueDto issueDto : authorizedIssues) { @@ -140,40 +144,12 @@ public class ServerIssueFinder implements IssueFinder { return issueIds; } - private Map<Issue, Rule> getRulesByIssue(List<Issue> issues, Set<Integer> ruleIds) { - Map<Issue, Rule> rulesByIssue = newHashMap(); - Collection<Rule> rules = ruleFinder.findByIds(ruleIds); - for (Issue issue : issues) { - rulesByIssue.put(issue, findRule(issue, rules)); - } - return rulesByIssue; + private Collection<Rule> findRules(Set<Integer> ruleIds) { + return ruleFinder.findByIds(ruleIds); } - private Rule findRule(final Issue issue, Collection<Rule> rules) { - return Iterables.find(rules, new Predicate<Rule>() { - @Override - public boolean apply(Rule rule) { - return issue.ruleKey().equals(rule.ruleKey()); - } - }, null); - } - - private Map<Issue, Component> getComponentsByIssue(List<Issue> issues, Set<Integer> componentIds) { - Map<Issue, Component> componentsByIssue = newHashMap(); - Collection<Component> components = resourceDao.findByIds(componentIds); - for (Issue issue : issues) { - componentsByIssue.put(issue, findComponent(issue, components)); - } - return componentsByIssue; - } - - private Component findComponent(final Issue issue, Collection<Component> components) { - return Iterables.find(components, new Predicate<Component>() { - @Override - public boolean apply(Component component) { - return issue.componentKey().equals(component.key()); - } - }, null); + private Collection<Component> findComponents(Set<Integer> componentIds) { + return resourceDao.findByIds(componentIds); } private ListMultimap createActionPlansByIssue(Collection<ActionPlanIssueDto> actionPlanIssueDtos, Map<Long, Issue> issuesById) { @@ -185,7 +161,7 @@ public class ServerIssueFinder implements IssueFinder { return actionPlansByIssue; } - private void setActionPlans(List<Issue> issues, ListMultimap<Issue, ActionPlan> actionPlansByIssueKey){ + private void setActionPlans(List<Issue> issues, ListMultimap<Issue, ActionPlan> actionPlansByIssueKey) { for (Issue issue : issues) { DefaultIssue defaultIssue = (DefaultIssue) issue; List<ActionPlan> actionPlans = actionPlansByIssueKey.get(issue); @@ -200,17 +176,25 @@ public class ServerIssueFinder implements IssueFinder { static class DefaultResults implements Results { private final List<Issue> issues; - private final Paging paging; - private final Map<Issue, Rule> rulesByIssue; - private final Map<Issue, Component> componentsByIssue; + private final Map<RuleKey, Rule> rulesByKey = Maps.newHashMap(); + private final Map<String, Component> componentsByKey = Maps.newHashMap(); private final ListMultimap<Issue, ActionPlan> actionPlansByIssue; private final boolean securityExclusions; + private final Paging paging; - DefaultResults(List<Issue> issues, Map<Issue, Rule> rulesByIssue, Map<Issue, Component> componentsByIssue, ListMultimap<Issue, ActionPlan> actionPlansByIssue, + DefaultResults(List<Issue> issues, + Collection<Rule> rules, + Collection<Component> components, + ListMultimap<Issue, + ActionPlan> actionPlansByIssue, Paging paging, boolean securityExclusions) { this.issues = issues; - this.rulesByIssue = rulesByIssue; - this.componentsByIssue = componentsByIssue; + for (Rule rule : rules) { + rulesByKey.put(rule.ruleKey(), rule); + } + for (Component component : components) { + componentsByKey.put(component.key(), component); + } this.actionPlansByIssue = actionPlansByIssue; this.paging = paging; this.securityExclusions = securityExclusions; @@ -222,19 +206,19 @@ public class ServerIssueFinder implements IssueFinder { } public Rule rule(Issue issue) { - return rulesByIssue.get(issue); + return rulesByKey.get(issue.ruleKey()); } public Collection<Rule> rules() { - return rulesByIssue.values(); + return rulesByKey.values(); } public Component component(Issue issue) { - return componentsByIssue.get(issue); + return componentsByKey.get(issue.componentKey()); } public Collection<Component> components() { - return componentsByIssue.values(); + return componentsByKey.values(); } public Collection<ActionPlan> actionPlans(Issue issue) { diff --git a/sonar-server/src/main/java/org/sonar/server/issue/JRubyApiIssues.java b/sonar-server/src/main/java/org/sonar/server/issue/WebIssuesApi.java index c1170d27577..35d9f60a4b5 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/JRubyApiIssues.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/WebIssuesApi.java @@ -26,7 +26,8 @@ import com.google.common.collect.Lists; import com.google.common.primitives.Ints; import org.sonar.api.issue.IssueFinder; import org.sonar.api.issue.IssueQuery; -import org.sonar.api.issue.JRubyIssues; +import org.sonar.api.issue.WebIssues; +import org.sonar.api.issue.WebIssues; import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.DateUtils; import org.sonar.api.web.UserRole; @@ -44,11 +45,11 @@ import java.util.Map; * * @since 3.6 */ -public class JRubyApiIssues implements JRubyIssues { +public class WebIssuesApi implements WebIssues { private final IssueFinder finder; - public JRubyApiIssues(IssueFinder f) { + public WebIssuesApi(IssueFinder f) { this.finder = f; } diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index f78b78f1316..7482610dd25 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -77,11 +77,11 @@ import org.sonar.server.notifications.NotificationService; import org.sonar.server.notifications.reviews.ReviewsNotificationManager; import org.sonar.server.plugins.*; import org.sonar.server.qualitymodel.DefaultModelManager; -import org.sonar.server.rule.JRubyRules; +import org.sonar.server.rule.WebRules; import org.sonar.server.rules.ProfilesConsole; import org.sonar.server.rules.RulesConsole; import org.sonar.server.startup.*; -import org.sonar.server.text.JRubyText; +import org.sonar.server.text.WebText; import org.sonar.server.text.MacroInterpreter; import org.sonar.server.ui.*; @@ -245,15 +245,15 @@ public final class Platform { servicesContainer.addSingleton(IssueWorkflow.class); servicesContainer.addSingleton(ServerIssueActions.class); servicesContainer.addSingleton(ServerIssueFinder.class); - servicesContainer.addSingleton(JRubyApiIssues.class); + servicesContainer.addSingleton(WebIssuesApi.class); servicesContainer.addSingleton(JRubyInternalIssues.class); // rules - servicesContainer.addSingleton(JRubyRules.class); + servicesContainer.addSingleton(WebRules.class); // text servicesContainer.addSingleton(MacroInterpreter.class); - servicesContainer.addSingleton(JRubyText.class); + servicesContainer.addSingleton(WebText.class); // Notifications servicesContainer.addSingleton(EmailSettings.class); diff --git a/sonar-server/src/main/java/org/sonar/server/rule/JRubyRules.java b/sonar-server/src/main/java/org/sonar/server/rule/WebRules.java index bd9e13ddff0..bb56bd0f2a5 100644 --- a/sonar-server/src/main/java/org/sonar/server/rule/JRubyRules.java +++ b/sonar-server/src/main/java/org/sonar/server/rule/WebRules.java @@ -28,11 +28,11 @@ import org.sonar.server.platform.UserSession; /** * Used through ruby code <pre>Internal.rules</pre> */ -public class JRubyRules implements ServerComponent, Startable { +public class WebRules implements ServerComponent, Startable { private final RuleI18nManager i18n; - public JRubyRules(RuleI18nManager i18n) { + public WebRules(RuleI18nManager i18n) { this.i18n = i18n; } diff --git a/sonar-server/src/main/java/org/sonar/server/text/JRubyText.java b/sonar-server/src/main/java/org/sonar/server/text/WebText.java index 7c8fd2a5dc4..adf198d9ed4 100644 --- a/sonar-server/src/main/java/org/sonar/server/text/JRubyText.java +++ b/sonar-server/src/main/java/org/sonar/server/text/WebText.java @@ -26,12 +26,12 @@ import org.sonar.markdown.Markdown; import java.util.List; -public class JRubyText implements ServerComponent { +public class WebText implements ServerComponent { private final MacroInterpreter macroInterpreter; private final HtmlSourceDecorator sourceDecorator; - public JRubyText(MacroInterpreter macroInterpreter, HtmlSourceDecorator sourceDecorator) { + public WebText(MacroInterpreter macroInterpreter, HtmlSourceDecorator sourceDecorator) { this.macroInterpreter = macroInterpreter; this.sourceDecorator = sourceDecorator; } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb index 8a2a7b9f9b5..cfaf0cf18f4 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/issues_controller.rb @@ -32,7 +32,8 @@ class Api::IssuesController < Api::ApiController { :securityExclusions => results.securityExclusions, :paging => paging_to_json(results.paging), - :issues => results.issues.map { |issue| issue_to_json(issue) } + :issues => results.issues.map { |issue| issue_to_json(issue) }, + :rules => results.rules.map { |rule| rule_to_json(rule) } } ) end @@ -206,6 +207,15 @@ class Api::IssuesController < Api::ApiController } end + def rule_to_json(rule) + l10n_name = Internal.rules.l10nRuleName(rule) + l10n_desc = Internal.rules.l10nRuleDescription(rule) + json = {:key => rule.getKey()} + json[:name] = l10n_name if l10n_name + json[:desc] = l10n_desc if l10n_desc + json + end + def paging_to_json(paging) { :pageIndex => paging.pageIndex, diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb index 332bc95fdc2..85717fc270e 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/models/internal.rb @@ -27,15 +27,15 @@ class Internal end def self.issues_api - component(Java::OrgSonarApiIssue::JRubyIssues.java_class) + component(Java::OrgSonarApiIssue::WebIssues.java_class) end def self.text - component(Java::OrgSonarServerText::JRubyText.java_class) + component(Java::OrgSonarServerText::WebText.java_class) end def self.rules - component(Java::OrgSonarServerRule::JRubyRules.java_class) + component(Java::OrgSonarServerRule::WebRules.java_class) end private diff --git a/sonar-server/src/test/java/org/sonar/server/issue/ServerIssueFinderTest.java b/sonar-server/src/test/java/org/sonar/server/issue/ServerIssueFinderTest.java index d2090f4da40..1bd38633d77 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/ServerIssueFinderTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/ServerIssueFinderTest.java @@ -20,7 +20,6 @@ package org.sonar.server.issue; import org.apache.ibatis.session.SqlSession; -import org.junit.Before; import org.junit.Test; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -56,30 +55,18 @@ import static org.mockito.Mockito.*; public class ServerIssueFinderTest { - MyBatis mybatis; - ServerIssueFinder finder; - - IssueDao issueDao; - AuthorizationDao authorizationDao; - DefaultRuleFinder ruleFinder; - ResourceDao resourceDao; - ActionPlanIssueDao actionPlanIssueDao; - - @Before - public void before() { - mybatis = mock(MyBatis.class); - issueDao = mock(IssueDao.class); - authorizationDao = mock(AuthorizationDao.class); - ruleFinder = mock(DefaultRuleFinder.class); - resourceDao = mock(ResourceDao.class); - actionPlanIssueDao = mock(ActionPlanIssueDao.class); - finder = new ServerIssueFinder(mybatis, issueDao, authorizationDao, ruleFinder, resourceDao, actionPlanIssueDao); - } + MyBatis mybatis = mock(MyBatis.class); + IssueDao issueDao = mock(IssueDao.class); + AuthorizationDao authorizationDao = mock(AuthorizationDao.class); + DefaultRuleFinder ruleFinder = mock(DefaultRuleFinder.class); + ResourceDao resourceDao = mock(ResourceDao.class); + ActionPlanIssueDao actionPlanIssueDao = mock(ActionPlanIssueDao.class); + ServerIssueFinder finder = new ServerIssueFinder(mybatis, issueDao, authorizationDao, ruleFinder, resourceDao, actionPlanIssueDao); @Test public void should_find_issues() { grantAccessRights(); - IssueQuery issueQuery = mock(IssueQuery.class); + IssueQuery query = IssueQuery.builder().build(); IssueDto issue1 = new IssueDto().setId(1L).setRuleId(50).setResourceId(123) .setComponentKey_unit_test_only("Action.java") @@ -90,10 +77,10 @@ public class ServerIssueFinderTest { .setRuleKey_unit_test_only("squid", "AvoidCycle") .setStatus("OPEN").setResolution("OPEN"); List<IssueDto> dtoList = newArrayList(issue1, issue2); - when(issueDao.selectIssueIdsAndComponentsId(eq(issueQuery), any(SqlSession.class))).thenReturn(dtoList); + when(issueDao.selectIssueIdsAndComponentsId(eq(query), any(SqlSession.class))).thenReturn(dtoList); when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); - IssueFinder.Results results = finder.find(issueQuery, null, UserRole.USER); + IssueFinder.Results results = finder.find(query, null, UserRole.USER); assertThat(results.issues()).hasSize(2); Issue issue = results.issues().iterator().next(); assertThat(issue.componentKey()).isEqualTo("Action.java"); @@ -103,8 +90,7 @@ public class ServerIssueFinderTest { @Test public void should_find_only_authorized_issues() { - IssueQuery issueQuery = mock(IssueQuery.class); - when(issueQuery.pageSize()).thenReturn(100); + IssueQuery query = IssueQuery.builder().pageSize(100).build(); IssueDto issue1 = new IssueDto().setId(1L).setRuleId(50).setResourceId(123) .setComponentKey_unit_test_only("Action.java") @@ -115,11 +101,11 @@ public class ServerIssueFinderTest { .setRuleKey_unit_test_only("squid", "AvoidCycle") .setStatus("OPEN").setResolution("OPEN"); List<IssueDto> dtoList = newArrayList(issue1, issue2); - when(issueDao.selectIssueIdsAndComponentsId(eq(issueQuery), any(SqlSession.class))).thenReturn(dtoList); + when(issueDao.selectIssueIdsAndComponentsId(eq(query), any(SqlSession.class))).thenReturn(dtoList); when(authorizationDao.keepAuthorizedComponentIds(anySet(), anyInt(), anyString(), any(SqlSession.class))).thenReturn(newHashSet(123)); when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(newArrayList(issue1)); - IssueFinder.Results results = finder.find(issueQuery, null, UserRole.USER); + IssueFinder.Results results = finder.find(query, null, UserRole.USER); verify(issueDao).selectByIds(eq(newHashSet(1L)), any(SqlSession.class)); assertThat(results.securityExclusions()).isTrue(); @@ -129,9 +115,7 @@ public class ServerIssueFinderTest { public void should_find_paginate_result() { grantAccessRights(); - IssueQuery issueQuery = mock(IssueQuery.class); - when(issueQuery.pageSize()).thenReturn(1); - when(issueQuery.pageIndex()).thenReturn(1); + IssueQuery query = IssueQuery.builder().pageSize(1).pageIndex(1).build(); IssueDto issue1 = new IssueDto().setId(1L).setRuleId(50).setResourceId(123) .setComponentKey_unit_test_only("Action.java") @@ -142,10 +126,10 @@ public class ServerIssueFinderTest { .setRuleKey_unit_test_only("squid", "AvoidCycle") .setStatus("OPEN").setResolution("OPEN"); List<IssueDto> dtoList = newArrayList(issue1, issue2); - when(issueDao.selectIssueIdsAndComponentsId(eq(issueQuery), any(SqlSession.class))).thenReturn(dtoList); + when(issueDao.selectIssueIdsAndComponentsId(eq(query), any(SqlSession.class))).thenReturn(dtoList); when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); - IssueFinder.Results results = finder.find(issueQuery, null, UserRole.USER); + IssueFinder.Results results = finder.find(query, null, UserRole.USER); assertThat(results.paging().offset()).isEqualTo(0); assertThat(results.paging().total()).isEqualTo(2); assertThat(results.paging().pages()).isEqualTo(2); @@ -174,7 +158,7 @@ public class ServerIssueFinderTest { when(ruleFinder.findByIds(anyCollection())).thenReturn(newArrayList(rule)); grantAccessRights(); - IssueQuery issueQuery = mock(IssueQuery.class); + IssueQuery query = IssueQuery.builder().build(); IssueDto issue1 = new IssueDto().setId(1L).setRuleId(50).setResourceId(123) .setComponentKey_unit_test_only("Action.java") @@ -185,10 +169,10 @@ public class ServerIssueFinderTest { .setRuleKey_unit_test_only("squid", "AvoidCycle") .setStatus("OPEN").setResolution("OPEN"); List<IssueDto> dtoList = newArrayList(issue1, issue2); - when(issueDao.selectIssueIdsAndComponentsId(eq(issueQuery), any(SqlSession.class))).thenReturn(dtoList); + when(issueDao.selectIssueIdsAndComponentsId(eq(query), any(SqlSession.class))).thenReturn(dtoList); when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); - IssueFinder.Results results = finder.find(issueQuery, null, UserRole.USER); + IssueFinder.Results results = finder.find(query, null, UserRole.USER); assertThat(results.issues()).hasSize(2); Issue issue = results.issues().iterator().next(); assertThat(results.issues()).hasSize(2); @@ -202,7 +186,7 @@ public class ServerIssueFinderTest { when(resourceDao.findByIds(anyCollection())).thenReturn(newArrayList(component)); grantAccessRights(); - IssueQuery issueQuery = mock(IssueQuery.class); + IssueQuery query = IssueQuery.builder().build(); IssueDto issue1 = new IssueDto().setId(1L).setRuleId(50).setResourceId(123) .setComponentKey_unit_test_only("Action.java") @@ -213,11 +197,11 @@ public class ServerIssueFinderTest { .setRuleKey_unit_test_only("squid", "AvoidCycle") .setStatus("OPEN").setResolution("OPEN"); List<IssueDto> dtoList = newArrayList(issue1, issue2); - when(issueDao.selectIssueIdsAndComponentsId(eq(issueQuery), any(SqlSession.class))).thenReturn(dtoList); + when(issueDao.selectIssueIdsAndComponentsId(eq(query), any(SqlSession.class))).thenReturn(dtoList); when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); - IssueFinder.Results results = finder.find(issueQuery, null, UserRole.USER); + IssueFinder.Results results = finder.find(query, null, UserRole.USER); assertThat(results.issues()).hasSize(2); Issue issue = results.issues().iterator().next(); assertThat(results.issues()).hasSize(2); @@ -231,7 +215,7 @@ public class ServerIssueFinderTest { ActionPlanIssueDto actionPlanIssueDto2 = new ActionPlanIssueDto().setIssueId(2L).setKee("B").setName("Long term"); grantAccessRights(); - IssueQuery issueQuery = mock(IssueQuery.class); + IssueQuery query = IssueQuery.builder().build(); IssueDto issue1 = new IssueDto().setId(1L).setRuleId(50).setResourceId(123).setKey("ABC") .setComponentKey_unit_test_only("Action.java") @@ -242,13 +226,13 @@ public class ServerIssueFinderTest { .setRuleKey_unit_test_only("squid", "AvoidCycle") .setStatus("OPEN").setResolution("OPEN"); List<IssueDto> dtoList = newArrayList(issue1, issue2); - when(issueDao.selectIssueIdsAndComponentsId(eq(issueQuery), any(SqlSession.class))).thenReturn(dtoList); + when(issueDao.selectIssueIdsAndComponentsId(eq(query), any(SqlSession.class))).thenReturn(dtoList); when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(dtoList); when(actionPlanIssueDao.findByIssueIds(anyCollection(), any(SqlSession.class))).thenReturn(newArrayList(actionPlanIssueDto1, actionPlanIssueDto2)); - IssueFinder.Results results = finder.find(issueQuery, null, UserRole.USER); + IssueFinder.Results results = finder.find(query, null, UserRole.USER); assertThat(results.issues()).hasSize(2); Issue issue = results.issues().iterator().next(); assertThat(results.issues()).hasSize(2); @@ -258,12 +242,12 @@ public class ServerIssueFinderTest { @Test public void should_get_empty_result_when_no_issue() { grantAccessRights(); - IssueQuery issueQuery = mock(IssueQuery.class); - when(issueDao.selectIssueIdsAndComponentsId(eq(issueQuery), any(SqlSession.class))).thenReturn(Collections.<IssueDto>emptyList()); + IssueQuery query = IssueQuery.builder().build(); + when(issueDao.selectIssueIdsAndComponentsId(eq(query), any(SqlSession.class))).thenReturn(Collections.<IssueDto>emptyList()); when(issueDao.selectByIds(anyCollection(), any(SqlSession.class))).thenReturn(Collections.<IssueDto>emptyList()); - IssueFinder.Results results = finder.find(issueQuery, null, UserRole.USER); + IssueFinder.Results results = finder.find(query, null, UserRole.USER); assertThat(results.issues()).isEmpty(); assertThat(results.rules()).isEmpty(); assertThat(results.components()).isEmpty(); diff --git a/sonar-server/src/test/java/org/sonar/server/issue/JRubyApiIssuesTest.java b/sonar-server/src/test/java/org/sonar/server/issue/WebIssuesApiTest.java index ed742c876b8..1ba994bbdf4 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/JRubyApiIssuesTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/WebIssuesApiTest.java @@ -39,10 +39,10 @@ import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.*; -public class JRubyApiIssuesTest { +public class WebIssuesApiTest { IssueFinder finder = mock(IssueFinder.class); - JRubyApiIssues facade = new JRubyApiIssues(finder); + WebIssuesApi facade = new WebIssuesApi(finder); @Test public void test_find() throws Exception { @@ -73,7 +73,7 @@ public class JRubyApiIssuesTest { map.put("pageSize", 10l); map.put("pageIndex", 50); - IssueQuery query = new JRubyApiIssues(finder).toQuery(map); + IssueQuery query = new WebIssuesApi(finder).toQuery(map); assertThat(query.issueKeys()).containsOnly("ABCDE1234"); assertThat(query.severities()).containsOnly("MAJOR", "MINOR"); assertThat(query.statuses()).containsOnly("CLOSED"); @@ -92,20 +92,20 @@ public class JRubyApiIssuesTest { @Test public void should_parse_list_of_rules() { - assertThat(JRubyApiIssues.toRules(null)).isNull(); - assertThat(JRubyApiIssues.toRules("")).isEmpty(); - assertThat(JRubyApiIssues.toRules("squid:AvoidCycle")).containsOnly(RuleKey.of("squid", "AvoidCycle")); - assertThat(JRubyApiIssues.toRules("squid:AvoidCycle,findbugs:NullRef")).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef")); - assertThat(JRubyApiIssues.toRules(asList("squid:AvoidCycle", "findbugs:NullRef"))).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef")); + assertThat(WebIssuesApi.toRules(null)).isNull(); + assertThat(WebIssuesApi.toRules("")).isEmpty(); + assertThat(WebIssuesApi.toRules("squid:AvoidCycle")).containsOnly(RuleKey.of("squid", "AvoidCycle")); + assertThat(WebIssuesApi.toRules("squid:AvoidCycle,findbugs:NullRef")).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef")); + assertThat(WebIssuesApi.toRules(asList("squid:AvoidCycle", "findbugs:NullRef"))).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef")); } @Test public void should_parse_list_of_strings() { - assertThat(JRubyApiIssues.toStrings(null)).isNull(); - assertThat(JRubyApiIssues.toStrings("")).isEmpty(); - assertThat(JRubyApiIssues.toStrings("foo")).containsOnly("foo"); - assertThat(JRubyApiIssues.toStrings("foo,bar")).containsOnly("foo", "bar"); - assertThat(JRubyApiIssues.toStrings(asList("foo", "bar"))).containsOnly("foo", "bar"); + assertThat(WebIssuesApi.toStrings(null)).isNull(); + assertThat(WebIssuesApi.toStrings("")).isEmpty(); + assertThat(WebIssuesApi.toStrings("foo")).containsOnly("foo"); + assertThat(WebIssuesApi.toStrings("foo,bar")).containsOnly("foo", "bar"); + assertThat(WebIssuesApi.toStrings(asList("foo", "bar"))).containsOnly("foo", "bar"); } diff --git a/sonar-server/src/test/java/org/sonar/server/rule/JRubyRulesTest.java b/sonar-server/src/test/java/org/sonar/server/rule/WebRulesTest.java index b84a2bd1147..390010080da 100644 --- a/sonar-server/src/test/java/org/sonar/server/rule/JRubyRulesTest.java +++ b/sonar-server/src/test/java/org/sonar/server/rule/WebRulesTest.java @@ -30,10 +30,10 @@ import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class JRubyRulesTest { +public class WebRulesTest { RuleI18nManager i18n = mock(RuleI18nManager.class); - JRubyRules facade = new JRubyRules(i18n); + WebRules facade = new WebRules(i18n); @Test public void should_get_localized_rule_name() { diff --git a/sonar-server/src/test/java/org/sonar/server/text/JRubyTextTest.java b/sonar-server/src/test/java/org/sonar/server/text/WebTextTest.java index feb71d9972d..ffb168f73d1 100644 --- a/sonar-server/src/test/java/org/sonar/server/text/JRubyTextTest.java +++ b/sonar-server/src/test/java/org/sonar/server/text/WebTextTest.java @@ -25,11 +25,11 @@ import org.sonar.core.source.HtmlSourceDecorator; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.*; -public class JRubyTextTest { +public class WebTextTest { MacroInterpreter macroInterpreter = mock(MacroInterpreter.class); HtmlSourceDecorator sourceDecorator = mock(HtmlSourceDecorator.class); - JRubyText text = new JRubyText(macroInterpreter, sourceDecorator); + WebText text = new WebText(macroInterpreter, sourceDecorator); @Test public void interpretMacros() throws Exception { |