diff options
9 files changed, 194 insertions, 20 deletions
diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/IssueMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/IssueMapper.xml index e916edbc1a7..bb1703815de 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/IssueMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/IssueMapper.xml @@ -95,6 +95,9 @@ <if test="components != null and components.size() > 0"> , projects p, snapshots root, snapshots s </if> + <if test="ruleRepository != null and rule != null"> + , rules r + </if> <where> <if test="components != null and components.size() > 0"> and p.enabled=${_true} @@ -147,6 +150,16 @@ <foreach item="assigneeLogin" index="index" collection="assigneeLogins" open="(" separator="," close=")">#{assigneeLogin} </foreach> </if> + <if test="ruleRepository != null and rule != null"> + and r.plugin_name = #{ruleRepository} and r.plugin_rule_key = #{rule} + and i.rule_id = r.id + </if> + <if test="createdAfter"> + and i.created_at > #{createdAfter} + </if> + <if test="createdBefore"> + and i.created_at < #{createdBefore} + </if> </where> </sql> diff --git a/sonar-core/src/test/java/org/sonar/core/issue/IssueDaoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/IssueDaoTest.java index e6490dc035d..9d9c7d10cce 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/IssueDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/IssueDaoTest.java @@ -158,6 +158,25 @@ public class IssueDaoTest extends AbstractDaoTestCase { } @Test + public void should_find_issue_by_rule() { + setupData("select"); + + IssueQuery issueQuery = IssueQuery.builder().rule("rule").ruleRepository("repo").build(); + assertThat(dao.select(issueQuery)).hasSize(4); + } + + @Test + public void should_find_issue_by_date_creation() { + setupData("select"); + + IssueQuery issueQuery = IssueQuery.builder().createdAfter(DateUtils.parseDate("2013-04-15")).build(); + assertThat(dao.select(issueQuery)).hasSize(1); + + issueQuery = IssueQuery.builder().createdBefore(DateUtils.parseDate("2013-04-17")).build(); + assertThat(dao.select(issueQuery)).hasSize(2); + } + + @Test public void should_return_issues_from_resource_tree() { setupData("select-with-component-children"); diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/select.xml b/sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/select.xml index 1bec8e838e8..73899ccbaf8 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/select.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/IssueDaoTest/select.xml @@ -40,7 +40,7 @@ assignee_login="user" person_id="[null]" data="[null]" - created_at="[null]" + created_at="2013-04-16" updated_at="[null]" closed_at="[null]" /> @@ -64,7 +64,7 @@ assignee_login="user" person_id="[null]" data="[null]" - created_at="[null]" + created_at="2013-04-10" updated_at="[null]" closed_at="[null]" /> @@ -157,4 +157,11 @@ islast="[true]" /> + + <rules + id="500" + plugin_name="repo" + plugin_rule_key="rule" + /> + </dataset> 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 c227aed75ba..e7cf30e7cf7 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 @@ -23,6 +23,7 @@ package org.sonar.api.issue; import com.google.common.base.Preconditions; import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import java.util.Date; import java.util.List; /** @@ -37,8 +38,12 @@ public class IssueQuery { private final List<String> statuses; private final List<String> resolutions; private final List<String> components; + private final String ruleRepository; + private final String rule; private final List<String> userLogins; private final List<String> assigneeLogins; + private final Date createdAfter; + private final Date createdBefore; private final int limit, offset; private IssueQuery(Builder builder) { @@ -47,8 +52,12 @@ public class IssueQuery { this.statuses = builder.statuses; this.resolutions = builder.resolutions; this.components = builder.components; + this.ruleRepository = builder.ruleRepository; + this.rule = builder.rule; this.userLogins = builder.userLogins; this.assigneeLogins = builder.assigneeLogins; + this.createdAfter = builder.createdAfter; + this.createdBefore = builder.createdBefore; this.limit = builder.limit; this.offset = builder.offset; } @@ -73,6 +82,14 @@ public class IssueQuery { return components; } + public String ruleRepository() { + return ruleRepository; + } + + public String rule() { + return rule; + } + public List<String> userLogins() { return userLogins; } @@ -81,6 +98,14 @@ public class IssueQuery { return assigneeLogins; } + public Date createdAfter() { + return createdAfter; + } + + public Date createdBefore() { + return createdBefore; + } + public int limit() { return limit; } @@ -112,8 +137,12 @@ public class IssueQuery { private List<String> statuses; private List<String> resolutions; private List<String> components; + private String ruleRepository; + private String rule; private List<String> userLogins; private List<String> assigneeLogins; + private Date createdAfter; + private Date createdBefore; private int limit = DEFAULT_LIMIT; private int offset = DEFAULT_OFFSET; @@ -145,6 +174,16 @@ public class IssueQuery { return this; } + public Builder ruleRepository(String ruleRepository) { + this.ruleRepository = ruleRepository; + return this; + } + + public Builder rule(String rule) { + this.rule = rule; + return this; + } + public Builder userLogins(List<String> l) { this.userLogins = l; return this; @@ -155,6 +194,16 @@ public class IssueQuery { return this; } + public Builder createdAfter(Date createdAfter) { + this.createdAfter = createdAfter; + return this; + } + + public Builder createdBefore(Date createdBefore) { + this.createdBefore = createdBefore; + return this; + } + public Builder limit(Integer i) { Preconditions.checkArgument(i == null || i.intValue() > 0, "Limit must be greater than 0 (got " + i + ")"); Preconditions.checkArgument(i == null || i.intValue() < MAX_LIMIT, "Limit must be less than " + MAX_LIMIT + " (got " + i + ")"); diff --git a/sonar-server/src/main/java/org/sonar/server/issue/DefaultJRubyIssues.java b/sonar-server/src/main/java/org/sonar/server/issue/DefaultJRubyIssues.java index a441ee6a3c8..0b931981245 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/DefaultJRubyIssues.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/DefaultJRubyIssues.java @@ -24,8 +24,10 @@ import com.google.common.collect.Lists; import org.sonar.api.issue.IssueFinder; import org.sonar.api.issue.IssueQuery; import org.sonar.api.issue.JRubyIssues; +import org.sonar.api.utils.DateUtils; import org.sonar.server.ui.JRubyFacades; +import java.util.Date; import java.util.List; import java.util.Map; @@ -54,8 +56,12 @@ public class DefaultJRubyIssues implements JRubyIssues { builder.statuses(toStringList(props.get("statuses"))); builder.resolutions(toStringList(props.get("resolutions"))); builder.components(toStringList(props.get("components"))); + builder.rule(toString(props.get("rule"))); + builder.ruleRepository(toString(props.get("ruleRepository"))); builder.userLogins(toStringList(props.get("userLogins"))); builder.assigneeLogins(toStringList(props.get("assigneeLogins"))); + builder.createdAfter(toDate(props.get("createdAfter"))); + builder.createdBefore(toDate(props.get("createdBefore"))); builder.limit(toInteger(props.get("limit"))); builder.offset(toInteger(props.get("offset"))); return builder.build(); @@ -84,6 +90,23 @@ public class DefaultJRubyIssues implements JRubyIssues { return null; } + String toString(Object o) { + if (o instanceof String) { + return ((String) o); + } + return null; + } + + Date toDate(Object o){ + if (o instanceof Date) { + return (Date) o; + } + if (o instanceof String) { + return DateUtils.parseDateTime((String) o); + } + return null; + } + public void start() { // used to force pico to instantiate the singleton at startup } diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb index 9a6bced2e04..d32ca9e5518 100644 --- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb +++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/resource_controller.rb @@ -474,10 +474,9 @@ class ResourceController < ApplicationController options['severities'] = rule_param else - # TODO rule = Rule.by_key_or_id(rule_param) - #options[:ruleKey] = rule.key - #options[:ruleRepository] = rule.key + options['rule'] = rule.plugin_rule_key + options['ruleRepository'] = rule.repository_key end end @@ -485,8 +484,7 @@ class ResourceController < ApplicationController if @period date = @snapshot.period_datetime(@period) if date - # TODO - #options[:created_after]=date.advance(:minutes => 1) + options['createdAfter'] = date end end diff --git a/sonar-server/src/test/java/org/sonar/server/issue/DefaultJRubyIssuesTest.java b/sonar-server/src/test/java/org/sonar/server/issue/DefaultJRubyIssuesTest.java index ecfcbe7dfcd..e8446364eb9 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/DefaultJRubyIssuesTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/DefaultJRubyIssuesTest.java @@ -25,7 +25,7 @@ import org.junit.Test; import org.mockito.ArgumentMatcher; import org.sonar.api.issue.IssueFinder; import org.sonar.api.issue.IssueQuery; -import org.sonar.server.issue.DefaultJRubyIssues; +import org.sonar.api.utils.DateUtils; import java.util.Map; @@ -34,9 +34,7 @@ import static com.google.common.collect.Maps.newHashMap; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.*; public class DefaultJRubyIssuesTest { @@ -64,6 +62,10 @@ public class DefaultJRubyIssuesTest { map.put("components", newArrayList("org.apache")); map.put("userLogins", newArrayList("marilyn")); map.put("assigneeLogins", newArrayList("joanna")); + map.put("createdAfter", "2013-04-16T09:08:24+0200"); + map.put("createdBefore", "2013-04-17T09:08:24+0200"); + map.put("rule", "rule"); + map.put("ruleRepository", "ruleRepository"); map.put("limit", 10); map.put("offset", 50); @@ -74,6 +76,10 @@ public class DefaultJRubyIssuesTest { assertThat(query.resolutions()).containsOnly("FALSE-POSITIVE"); assertThat(query.userLogins()).containsOnly("marilyn"); assertThat(query.assigneeLogins()).containsOnly("joanna"); + assertThat(query.rule()).isEqualTo("rule"); + assertThat(query.ruleRepository()).isEqualTo("ruleRepository"); + assertThat(query.createdAfter()).isEqualTo(DateUtils.parseDateTime("2013-04-16T09:08:24+0200")); + assertThat(query.createdBefore()).isEqualTo(DateUtils.parseDateTime("2013-04-17T09:08:24+0200")); assertThat(query.limit()).isEqualTo(10); assertThat(query.offset()).isEqualTo(50); } diff --git a/sonar-ws-client/src/main/java/org/sonar/wsclient/services/IssueQuery.java b/sonar-ws-client/src/main/java/org/sonar/wsclient/services/IssueQuery.java index 988df66f723..a621517c384 100644 --- a/sonar-ws-client/src/main/java/org/sonar/wsclient/services/IssueQuery.java +++ b/sonar-ws-client/src/main/java/org/sonar/wsclient/services/IssueQuery.java @@ -19,6 +19,8 @@ */ package org.sonar.wsclient.services; +import java.util.Date; + /** * @since 3.6 */ @@ -32,10 +34,14 @@ public final class IssueQuery extends Query<Issue> { private String[] status; private String[] resolutions; private String[] components; - private String[] rules; + private String ruleRepository; + private String rule; private String[] userLogins; private String[] assigneeLogins; + private Date createdAfter; + private Date createdBefore; private Integer limit; + private Integer offset; private IssueQuery() { } @@ -102,12 +108,21 @@ public final class IssueQuery extends Query<Issue> { return this; } - public String[] getRules() { - return rules; + public String getRuleRepository() { + return ruleRepository; + } + + public IssueQuery setRuleRepository(String ruleRepository) { + this.ruleRepository = ruleRepository; + return this; + } + + public String getRule() { + return rule; } - public IssueQuery setRules(String... rules) { - this.rules = rules; + public IssueQuery setRule(String rule) { + this.rule = rule; return this; } @@ -129,6 +144,24 @@ public final class IssueQuery extends Query<Issue> { return this; } + public Date getCreatedAfter() { + return createdAfter; + } + + public IssueQuery setCreatedAfter(Date createdAfter) { + this.createdAfter = createdAfter; + return this; + } + + public Date getCreatedBefore() { + return createdBefore; + } + + public IssueQuery setCreatedBefore(Date createdBefore) { + this.createdBefore = createdBefore; + return this; + } + public Integer getLimit() { return limit; } @@ -138,6 +171,15 @@ public final class IssueQuery extends Query<Issue> { return this; } + public Integer getOffset() { + return offset; + } + + public IssueQuery setOffset(Integer offset) { + this.offset = offset; + return this; + } + @Override public String getUrl() { StringBuilder url = new StringBuilder(BASE_URL); @@ -148,10 +190,14 @@ public final class IssueQuery extends Query<Issue> { appendUrlParameter(url, "status", status); appendUrlParameter(url, "resolutions", resolutions); appendUrlParameter(url, "components", components); - appendUrlParameter(url, "rules", rules); + appendUrlParameter(url, "ruleRepository", ruleRepository); + appendUrlParameter(url, "rule", rule); appendUrlParameter(url, "userLogins", userLogins); appendUrlParameter(url, "assigneeLogins", assigneeLogins); + appendUrlParameter(url, "createdAfter", createdAfter); + appendUrlParameter(url, "createdBefore", createdBefore); appendUrlParameter(url, "limit", limit); + appendUrlParameter(url, "offset", offset); return url.toString(); } diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/services/IssueQueryTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/services/IssueQueryTest.java index 1d620e483e2..2d7bb8a6684 100644 --- a/sonar-ws-client/src/test/java/org/sonar/wsclient/services/IssueQueryTest.java +++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/services/IssueQueryTest.java @@ -22,6 +22,8 @@ package org.sonar.wsclient.services; import org.junit.Test; +import java.text.SimpleDateFormat; + import static org.fest.assertions.Assertions.assertThat; public class IssueQueryTest extends QueryTestCase { @@ -41,13 +43,24 @@ public class IssueQueryTest extends QueryTestCase { .setLimit(1) .setMinSeverity("minSev") .setResolutions("resoltion1", "resolution2") - .setRules("rule1", "rule2") + .setRuleRepository("ruleRepo") + .setRule("rule") .setStatus("status1", "status2") .setSeverities("sev1", "sev2") - .setUserLogins("userLogin1", "userLogin2"); + .setUserLogins("userLogin1", "userLogin2") + ; assertThat(query.getUrl()).isEqualTo("/api/issues/search?keys=key1,key2&severities=sev1,sev2&minSeverity=minSev&status=status1,status2&" + - "resolutions=resoltion1,resolution2&components=component1,component2&rules=rule1,rule2&userLogins=userLogin1,userLogin2&" + + "resolutions=resoltion1,resolution2&components=component1,component2&ruleRepository=ruleRepo&rule=rule&userLogins=userLogin1,userLogin2&" + "assigneeLogins=assigneeLogin1,assigneeLogin2&limit=1&"); } + @Test + public void get_all_issues_by_created_at() throws Exception { + IssueQuery query = IssueQuery.create() + .setCreatedAfter(new SimpleDateFormat("yyyy-MM-dd").parse("2013-04-16")) + .setCreatedBefore(new SimpleDateFormat("yyyy-MM-dd").parse("2010-02-18")) + ; + assertThat(query.getUrl()).isEqualTo("/api/issues/search?createdAfter=Tue+Apr+16+00%3A00%3A00+CEST+2013&createdBefore=Thu+Feb+18+00%3A00%3A00+CET+2010&"); + } + } |