Browse Source

SONAR-7292 Sanitize IssuesWsParameters and add some missing actions in IssueService

tags/6.3-RC1
Julien Lancelot 7 years ago
parent
commit
2ce306a42f
26 changed files with 1000 additions and 646 deletions
  1. 12
    12
      it/it-tests/src/test/java/it/issue/IssueActionTest.java
  2. 118
    107
      it/it-tests/src/test/java/it/issue/IssueWorkflowTest.java
  3. 2
    2
      server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
  4. 41
    41
      server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java
  5. 51
    51
      server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
  6. 13
    7
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/AddCommentAction.java
  7. 15
    10
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/AssignAction.java
  8. 3
    1
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/AuthorsAction.java
  9. 13
    11
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/ComponentTagsAction.java
  10. 12
    9
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java
  11. 116
    116
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
  12. 12
    9
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/SetSeverityAction.java
  13. 18
    10
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/SetTagsAction.java
  14. 10
    8
      server/sonar-server/src/main/java/org/sonar/server/issue/ws/SetTypeAction.java
  15. 2
    3
      server/sonar-server/src/test/java/org/sonar/server/issue/ws/ComponentTagsActionTest.java
  16. 76
    75
      server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java
  17. 33
    33
      server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java
  18. 10
    1
      server/sonar-server/src/test/java/org/sonar/server/issue/ws/SetTagsActionTest.java
  19. 42
    0
      sonar-ws/src/main/java/org/sonarqube/ws/client/issue/AddCommentRequest.java
  20. 46
    0
      sonar-ws/src/main/java/org/sonarqube/ws/client/issue/AssignRequest.java
  21. 42
    0
      sonar-ws/src/main/java/org/sonarqube/ws/client/issue/DoTransitionRequest.java
  22. 119
    77
      sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesService.java
  23. 58
    55
      sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesWsParameters.java
  24. 42
    0
      sonar-ws/src/main/java/org/sonarqube/ws/client/issue/SetSeverityRequest.java
  25. 42
    0
      sonar-ws/src/main/java/org/sonarqube/ws/client/issue/SetTypeRequest.java
  26. 52
    8
      sonar-ws/src/test/java/org/sonarqube/ws/client/issue/IssuesServiceTest.java

+ 12
- 12
it/it-tests/src/test/java/it/issue/IssueActionTest.java View File

@@ -20,16 +20,17 @@
package it.issue;

import java.util.List;
import org.assertj.core.api.Assertions;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.issue.IssueQuery;
import org.sonarqube.ws.Issues;
import org.sonarqube.ws.Issues.Issue;
import org.sonarqube.ws.client.issue.AddCommentRequest;
import org.sonarqube.ws.client.issue.AssignRequest;
import org.sonarqube.ws.client.issue.IssuesService;
import org.sonarqube.ws.client.issue.SearchWsRequest;
import org.sonarqube.ws.client.issue.SetSeverityRequest;
import util.ProjectAnalysis;
import util.ProjectAnalysisRule;
import util.issue.IssueRule;
@@ -40,7 +41,6 @@ import static org.junit.Assert.fail;
import static org.sonarqube.ws.Common.Severity.BLOCKER;
import static util.ItUtils.newAdminWsClient;
import static util.ItUtils.toDatetime;
import static util.ItUtils.verifyHttpException;

public class IssueActionTest extends AbstractIssueTest {

@@ -73,7 +73,7 @@ public class IssueActionTest extends AbstractIssueTest {

@Test
public void add_comment() throws Exception {
Issues.Comment comment = issuesService.addComment(randomIssue.getKey(), "this is my *comment*").getIssue().getComments().getComments(0);
Issues.Comment comment = issuesService.addComment(new AddCommentRequest(randomIssue.getKey(), "this is my *comment*")).getIssue().getComments().getComments(0);

assertThat(comment.getKey()).isNotNull();
assertThat(comment.getHtmlText()).isEqualTo("this is my <strong>comment</strong>");
@@ -95,7 +95,7 @@ public class IssueActionTest extends AbstractIssueTest {
@Test
public void should_reject_blank_comment() throws Exception {
try {
issuesService.addComment(randomIssue.getKey(), " ");
issuesService.addComment(new AddCommentRequest(randomIssue.getKey(), " "));
fail();
} catch (org.sonarqube.ws.client.HttpException ex) {
assertThat(ex.code()).isEqualTo(400);
@@ -116,7 +116,7 @@ public class IssueActionTest extends AbstractIssueTest {
assertThat(searchIssuesBySeverities(componentKey, "BLOCKER")).isEmpty();

// increase the severity of an issue
adminIssueClient().setSeverity(randomIssue.getKey(), "BLOCKER");
issuesService.setSeverity(new SetSeverityRequest(randomIssue.getKey(), "BLOCKER"));

assertThat(searchIssuesBySeverities(componentKey, "BLOCKER")).hasSize(1);

@@ -138,7 +138,7 @@ public class IssueActionTest extends AbstractIssueTest {
Issues.SearchWsResponse response = issueRule.search(new SearchWsRequest().setIssues(singletonList(randomIssue.getKey())));
assertThat(response.getUsers().getUsersList()).isEmpty();

adminIssueClient().assign(randomIssue.getKey(), "admin");
issuesService.assign(new AssignRequest(randomIssue.getKey(), "admin"));
assertThat(issueRule.search(new SearchWsRequest().setAssignees(singletonList("admin"))).getIssuesList()).hasSize(1);

projectAnalysis.run();
@@ -151,10 +151,10 @@ public class IssueActionTest extends AbstractIssueTest {
assertThat(response.getUsers().getUsersList().stream().filter(user -> "Administrator".equals(user.getName())).findFirst()).isPresent();

// unassign
adminIssueClient().assign(randomIssue.getKey(), null);
issuesService.assign(new AssignRequest(randomIssue.getKey(), null));
reloaded = issueRule.getByKey(randomIssue.getKey());
assertThat(reloaded.hasAssignee()).isFalse();
Assertions.assertThat(searchIssues(IssueQuery.create().assignees("admin"))).isEmpty();
assertThat(issueRule.search(new SearchWsRequest().setAssignees(singletonList("admin"))).getIssuesList()).isEmpty();
}

/**
@@ -164,10 +164,10 @@ public class IssueActionTest extends AbstractIssueTest {
public void fail_assign_if_assignee_does_not_exist() {
assertThat(randomIssue.hasAssignee()).isFalse();
try {
adminIssueClient().assign(randomIssue.getKey(), "unknown");
issuesService.assign(new AssignRequest(randomIssue.getKey(), "unknown"));
fail();
} catch (Exception e) {
verifyHttpException(e, 400);
} catch (org.sonarqube.ws.client.HttpException ex) {
assertThat(ex.code()).isEqualTo(400);
}
}


+ 118
- 107
it/it-tests/src/test/java/it/issue/IssueWorkflowTest.java View File

@@ -21,37 +21,47 @@ package it.issue;

import java.util.List;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.wsclient.issue.Issue;
import org.sonar.wsclient.issue.IssueQuery;
import org.sonarqube.ws.Issues;
import org.sonarqube.ws.Issues.Issue;
import org.sonarqube.ws.client.issue.DoTransitionRequest;
import org.sonarqube.ws.client.issue.IssuesService;
import org.sonarqube.ws.client.issue.SearchWsRequest;
import util.ProjectAnalysis;
import util.ProjectAnalysisRule;
import util.issue.IssueRule;

import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static util.ItUtils.newAdminWsClient;
import static util.ItUtils.toDatetime;

public class IssueWorkflowTest extends AbstractIssueTest {

@Rule
public final ProjectAnalysisRule projectAnalysisRule = ProjectAnalysisRule.from(ORCHESTRATOR);

@ClassRule
public static final IssueRule issueRule = IssueRule.from(ORCHESTRATOR);

private ProjectAnalysis analysisWithIssues;
private ProjectAnalysis analysisWithoutIssues;
private IssuesService issuesService;

private Issue issue;

@Before
public void before() {
issuesService = newAdminWsClient(ORCHESTRATOR).issues();
String oneIssuePerFileProfileKey = projectAnalysisRule.registerProfile("/issue/IssueWorkflowTest/xoo-one-issue-per-line-profile.xml");
String analyzedProjectKey = projectAnalysisRule.registerProject("issue/workflow");
analysisWithIssues = projectAnalysisRule.newProjectAnalysis(analyzedProjectKey).withQualityProfile(oneIssuePerFileProfileKey);
analysisWithoutIssues = analysisWithIssues.withXooEmptyProfile();
analysisWithIssues.run();

issue = searchRandomIssue();
issue = issueRule.getRandomIssue();
}

/**
@@ -60,16 +70,17 @@ public class IssueWorkflowTest extends AbstractIssueTest {
*/
@Test
public void issue_is_closed_as_removed_when_rule_is_disabled() throws Exception {
List<Issue> issues = searchIssues(IssueQuery.create().rules("xoo:OneIssuePerLine"));
SearchWsRequest ruleSearchRequest = new SearchWsRequest().setRules(singletonList("xoo:OneIssuePerLine"));
List<Issue> issues = issueRule.search(ruleSearchRequest).getIssuesList();
assertThat(issues).isNotEmpty();

// re-analyze with profile "empty". The rule is disabled so the issues must be closed
analysisWithoutIssues.run();
issues = searchIssues(IssueQuery.create().rules("xoo:OneIssuePerLine"));
issues = issueRule.search(ruleSearchRequest).getIssuesList();
assertThat(issues).isNotEmpty();
for (Issue issue : issues) {
assertThat(issue.status()).isEqualTo("CLOSED");
assertThat(issue.resolution()).isEqualTo("REMOVED");
assertThat(issue.getStatus()).isEqualTo("CLOSED");
assertThat(issue.getResolution()).isEqualTo("REMOVED");
}
}

@@ -79,21 +90,21 @@ public class IssueWorkflowTest extends AbstractIssueTest {
@Test
public void user_should_confirm_issue() {
// mark as confirmed
adminIssueClient().doTransition(issue.key(), "confirm");
issuesService.doTransition(new DoTransitionRequest(issue.getKey(), "confirm"));

Issue confirmed = searchIssueByKey(issue.key());
assertThat(confirmed.status()).isEqualTo("CONFIRMED");
assertThat(confirmed.resolution()).isNull();
assertThat(confirmed.creationDate()).isEqualTo(issue.creationDate());
Issue confirmed = issueRule.getByKey(issue.getKey());
assertThat(confirmed.getStatus()).isEqualTo("CONFIRMED");
assertThat(confirmed.hasResolution()).isFalse();
assertThat(confirmed.getCreationDate()).isEqualTo(issue.getCreationDate());

// user unconfirm the issue
assertThat(transitions(confirmed.key())).contains("unconfirm");
adminIssueClient().doTransition(confirmed.key(), "unconfirm");
assertThat(transitions(confirmed.getKey())).contains("unconfirm");
issuesService.doTransition(new DoTransitionRequest(confirmed.getKey(), "unconfirm"));

Issue unconfirmed = searchIssueByKey(issue.key());
assertThat(unconfirmed.status()).isEqualTo("REOPENED");
assertThat(unconfirmed.resolution()).isNull();
assertThat(unconfirmed.creationDate()).isEqualTo(confirmed.creationDate());
Issue unconfirmed = issueRule.getByKey(issue.getKey());
assertThat(unconfirmed.getStatus()).isEqualTo("REOPENED");
assertThat(unconfirmed.hasResolution()).isFalse();
assertThat(unconfirmed.getCreationDate()).isEqualTo(confirmed.getCreationDate());
}

/**
@@ -102,21 +113,21 @@ public class IssueWorkflowTest extends AbstractIssueTest {
@Test
public void user_should_mark_as_false_positive_confirmed_issue() {
// mark as confirmed
adminIssueClient().doTransition(issue.key(), "confirm");
issuesService.doTransition(new DoTransitionRequest(issue.getKey(), "confirm"));

Issue confirmed = searchIssueByKey(issue.key());
assertThat(confirmed.status()).isEqualTo("CONFIRMED");
assertThat(confirmed.resolution()).isNull();
assertThat(confirmed.creationDate()).isEqualTo(issue.creationDate());
Issue confirmed = issueRule.getByKey(issue.getKey());
assertThat(confirmed.getStatus()).isEqualTo("CONFIRMED");
assertThat(confirmed.hasResolution()).isFalse();
assertThat(confirmed.getCreationDate()).isEqualTo(issue.getCreationDate());

// user mark the issue as false-positive
assertThat(transitions(confirmed.key())).contains("falsepositive");
adminIssueClient().doTransition(confirmed.key(), "falsepositive");
assertThat(transitions(confirmed.getKey())).contains("falsepositive");
issuesService.doTransition(new DoTransitionRequest(confirmed.getKey(), "falsepositive"));

Issue falsePositive = searchIssueByKey(issue.key());
assertThat(falsePositive.status()).isEqualTo("RESOLVED");
assertThat(falsePositive.resolution()).isEqualTo("FALSE-POSITIVE");
assertThat(falsePositive.creationDate()).isEqualTo(confirmed.creationDate());
Issue falsePositive = issueRule.getByKey(issue.getKey());
assertThat(falsePositive.getStatus()).isEqualTo("RESOLVED");
assertThat(falsePositive.getResolution()).isEqualTo("FALSE-POSITIVE");
assertThat(falsePositive.getCreationDate()).isEqualTo(confirmed.getCreationDate());
}

/**
@@ -125,18 +136,18 @@ public class IssueWorkflowTest extends AbstractIssueTest {
@Test
public void scan_should_close_no_more_existing_confirmed() {
// mark as confirmed
adminIssueClient().doTransition(issue.key(), "confirm");
Issue falsePositive = searchIssueByKey(issue.key());
assertThat(falsePositive.status()).isEqualTo("CONFIRMED");
assertThat(falsePositive.resolution()).isNull();
assertThat(falsePositive.creationDate()).isEqualTo(issue.creationDate());
issuesService.doTransition(new DoTransitionRequest(issue.getKey(), "confirm"));
Issue falsePositive = issueRule.getByKey(issue.getKey());
assertThat(falsePositive.getStatus()).isEqualTo("CONFIRMED");
assertThat(falsePositive.hasResolution()).isFalse();
assertThat(falsePositive.getCreationDate()).isEqualTo(issue.getCreationDate());

// scan without any rules -> confirmed is closed
analysisWithoutIssues.run();
Issue closed = searchIssueByKey(issue.key());
assertThat(closed.status()).isEqualTo("CLOSED");
assertThat(closed.resolution()).isEqualTo("REMOVED");
assertThat(closed.creationDate()).isEqualTo(issue.creationDate());
Issue closed = issueRule.getByKey(issue.getKey());
assertThat(closed.getStatus()).isEqualTo("CLOSED");
assertThat(closed.getResolution()).isEqualTo("REMOVED");
assertThat(closed.getCreationDate()).isEqualTo(issue.getCreationDate());
}

/**
@@ -145,25 +156,25 @@ public class IssueWorkflowTest extends AbstractIssueTest {
@Test
public void scan_should_reopen_unresolved_issue_but_marked_as_resolved() {
// mark as resolved
adminIssueClient().doTransition(issue.key(), "resolve");
Issue resolvedIssue = searchIssueByKey(issue.key());
assertThat(resolvedIssue.status()).isEqualTo("RESOLVED");
assertThat(resolvedIssue.resolution()).isEqualTo("FIXED");
assertThat(resolvedIssue.creationDate()).isEqualTo(issue.creationDate());
assertThat(resolvedIssue.updateDate().before(resolvedIssue.creationDate())).isFalse();
assertThat(resolvedIssue.updateDate().before(issue.updateDate())).isFalse();
issuesService.doTransition(new DoTransitionRequest(issue.getKey(), "resolve"));
Issue resolvedIssue = issueRule.getByKey(issue.getKey());
assertThat(resolvedIssue.getStatus()).isEqualTo("RESOLVED");
assertThat(resolvedIssue.getResolution()).isEqualTo("FIXED");
assertThat(resolvedIssue.getCreationDate()).isEqualTo(issue.getCreationDate());
assertThat(toDatetime(resolvedIssue.getUpdateDate())).isAfter(toDatetime(resolvedIssue.getCreationDate()));
assertThat(toDatetime(resolvedIssue.getUpdateDate())).isAfter(toDatetime(issue.getUpdateDate()));

// re-execute scan, with the same Q profile -> the issue has not been fixed
analysisWithIssues.run();

// reload issue
Issue reopenedIssue = searchIssueByKey(issue.key());
Issue reopenedIssue = issueRule.getByKey(issue.getKey());

// the issue has been reopened
assertThat(reopenedIssue.status()).isEqualTo("REOPENED");
assertThat(reopenedIssue.resolution()).isNull();
assertThat(reopenedIssue.creationDate()).isEqualTo(issue.creationDate());
assertThat(reopenedIssue.updateDate().before(issue.updateDate())).isFalse();
assertThat(reopenedIssue.getStatus()).isEqualTo("REOPENED");
assertThat(reopenedIssue.hasResolution()).isFalse();
assertThat(reopenedIssue.getCreationDate()).isEqualTo(issue.getCreationDate());
assertThat(toDatetime(reopenedIssue.getUpdateDate())).isAfter(toDatetime(issue.getUpdateDate()));
}

/**
@@ -172,24 +183,24 @@ public class IssueWorkflowTest extends AbstractIssueTest {
@Test
public void scan_should_close_resolved_issue() {
// mark as resolved
adminIssueClient().doTransition(issue.key(), "resolve");
Issue resolvedIssue = searchIssueByKey(issue.key());
assertThat(resolvedIssue.status()).isEqualTo("RESOLVED");
assertThat(resolvedIssue.resolution()).isEqualTo("FIXED");
assertThat(resolvedIssue.creationDate()).isEqualTo(issue.creationDate());
assertThat(resolvedIssue.closeDate()).isNull();
issuesService.doTransition(new DoTransitionRequest(issue.getKey(), "resolve"));
Issue resolvedIssue = issueRule.getByKey(issue.getKey());
assertThat(resolvedIssue.getStatus()).isEqualTo("RESOLVED");
assertThat(resolvedIssue.getResolution()).isEqualTo("FIXED");
assertThat(resolvedIssue.getCreationDate()).isEqualTo(issue.getCreationDate());
assertThat(resolvedIssue.hasCloseDate()).isFalse();

// re-execute scan without rules -> the issue is removed with resolution "REMOVED"
analysisWithoutIssues.run();

// reload issue
Issue closedIssue = searchIssueByKey(issue.key());
assertThat(closedIssue.status()).isEqualTo("CLOSED");
assertThat(closedIssue.resolution()).isEqualTo("REMOVED");
assertThat(closedIssue.creationDate()).isEqualTo(issue.creationDate());
assertThat(closedIssue.updateDate().before(resolvedIssue.updateDate())).isFalse();
assertThat(closedIssue.closeDate()).isNotNull();
assertThat(closedIssue.closeDate().before(closedIssue.creationDate())).isFalse();
Issue closedIssue = issueRule.getByKey(issue.getKey());
assertThat(closedIssue.getStatus()).isEqualTo("CLOSED");
assertThat(closedIssue.getResolution()).isEqualTo("REMOVED");
assertThat(closedIssue.getCreationDate()).isEqualTo(issue.getCreationDate());
assertThat(toDatetime(closedIssue.getUpdateDate())).isAfter(toDatetime(resolvedIssue.getUpdateDate()));
assertThat(closedIssue.hasCloseDate()).isTrue();
assertThat(toDatetime(closedIssue.getCloseDate())).isAfter(toDatetime(closedIssue.getCreationDate()));
}

/**
@@ -198,21 +209,21 @@ public class IssueWorkflowTest extends AbstractIssueTest {
@Test
public void user_should_reopen_issue_marked_as_resolved() {
// user marks issue as resolved
adminIssueClient().doTransition(issue.key(), "resolve");
Issue resolved = searchIssueByKey(issue.key());
assertThat(resolved.status()).isEqualTo("RESOLVED");
assertThat(resolved.resolution()).isEqualTo("FIXED");
assertThat(resolved.creationDate()).isEqualTo(issue.creationDate());
issuesService.doTransition(new DoTransitionRequest(issue.getKey(), "resolve"));
Issue resolved = issueRule.getByKey(issue.getKey());
assertThat(resolved.getStatus()).isEqualTo("RESOLVED");
assertThat(resolved.getResolution()).isEqualTo("FIXED");
assertThat(resolved.getCreationDate()).isEqualTo(issue.getCreationDate());

// user reopens the issue
assertThat(transitions(resolved.key())).contains("reopen");
adminIssueClient().doTransition(resolved.key(), "reopen");
Issue reopened = searchIssueByKey(resolved.key());
assertThat(reopened.status()).isEqualTo("REOPENED");
assertThat(reopened.resolution()).isNull();
assertThat(reopened.creationDate()).isEqualTo(resolved.creationDate());
assertThat(reopened.updateDate().before(resolved.updateDate())).isFalse();
assertThat(transitions(resolved.getKey())).contains("reopen");
adminIssueClient().doTransition(resolved.getKey(), "reopen");
Issue reopened = issueRule.getByKey(resolved.getKey());
assertThat(reopened.getStatus()).isEqualTo("REOPENED");
assertThat(reopened.hasResolution()).isFalse();
assertThat(reopened.getCreationDate()).isEqualTo(resolved.getCreationDate());
assertThat(toDatetime(reopened.getUpdateDate())).isAfterOrEqualsTo(toDatetime(resolved.getUpdateDate()));
}

/**
@@ -221,21 +232,21 @@ public class IssueWorkflowTest extends AbstractIssueTest {
@Test
public void scan_should_not_reopen_or_close_false_positives() {
// user marks issue as false-positive
adminIssueClient().doTransition(issue.key(), "falsepositive");
issuesService.doTransition(new DoTransitionRequest(issue.getKey(), "falsepositive"));

Issue falsePositive = searchIssueByKey(issue.key());
assertThat(falsePositive.status()).isEqualTo("RESOLVED");
assertThat(falsePositive.resolution()).isEqualTo("FALSE-POSITIVE");
assertThat(falsePositive.creationDate()).isEqualTo(issue.creationDate());
Issue falsePositive = issueRule.getByKey(issue.getKey());
assertThat(falsePositive.getStatus()).isEqualTo("RESOLVED");
assertThat(falsePositive.getResolution()).isEqualTo("FALSE-POSITIVE");
assertThat(falsePositive.getCreationDate()).isEqualTo(issue.getCreationDate());

// re-execute the same scan
analysisWithIssues.run();

// refresh
Issue reloaded = searchIssueByKey(falsePositive.key());
assertThat(reloaded.status()).isEqualTo("RESOLVED");
assertThat(reloaded.resolution()).isEqualTo("FALSE-POSITIVE");
assertThat(reloaded.creationDate()).isEqualTo(issue.creationDate());
Issue reloaded = issueRule.getByKey(falsePositive.getKey());
assertThat(reloaded.getStatus()).isEqualTo("RESOLVED");
assertThat(reloaded.getResolution()).isEqualTo("FALSE-POSITIVE");
assertThat(reloaded.getCreationDate()).isEqualTo(issue.getCreationDate());
// TODO check that update date has not been changed
}

@@ -245,18 +256,18 @@ public class IssueWorkflowTest extends AbstractIssueTest {
@Test
public void scan_should_close_no_more_existing_false_positive() {
// user marks as false-positive
adminIssueClient().doTransition(issue.key(), "falsepositive");
Issue falsePositive = searchIssueByKey(issue.key());
assertThat(falsePositive.status()).isEqualTo("RESOLVED");
assertThat(falsePositive.resolution()).isEqualTo("FALSE-POSITIVE");
assertThat(falsePositive.creationDate()).isEqualTo(issue.creationDate());
issuesService.doTransition(new DoTransitionRequest(issue.getKey(), "falsepositive"));
Issue falsePositive = issueRule.getByKey(issue.getKey());
assertThat(falsePositive.getStatus()).isEqualTo("RESOLVED");
assertThat(falsePositive.getResolution()).isEqualTo("FALSE-POSITIVE");
assertThat(falsePositive.getCreationDate()).isEqualTo(issue.getCreationDate());

// scan without any rules -> false-positive is closed
analysisWithoutIssues.run();
Issue closed = searchIssueByKey(issue.key());
assertThat(closed.status()).isEqualTo("CLOSED");
assertThat(closed.resolution()).isEqualTo("REMOVED");
assertThat(closed.creationDate()).isEqualTo(issue.creationDate());
Issue closed = issueRule.getByKey(issue.getKey());
assertThat(closed.getStatus()).isEqualTo("CLOSED");
assertThat(closed.getResolution()).isEqualTo("REMOVED");
assertThat(closed.getCreationDate()).isEqualTo(issue.getCreationDate());
}

/**
@@ -265,32 +276,32 @@ public class IssueWorkflowTest extends AbstractIssueTest {
@Test
public void user_should_reopen_false_positive() {
// user marks as false-positive
adminIssueClient().doTransition(issue.key(), "falsepositive");
issuesService.doTransition(new DoTransitionRequest(issue.getKey(), "falsepositive"));

Issue falsePositive = searchIssueByKey(issue.key());
assertThat(falsePositive.status()).isEqualTo("RESOLVED");
assertThat(falsePositive.resolution()).isEqualTo("FALSE-POSITIVE");
assertThat(falsePositive.creationDate()).isEqualTo(issue.creationDate());
Issue falsePositive = issueRule.getByKey(issue.getKey());
assertThat(falsePositive.getStatus()).isEqualTo("RESOLVED");
assertThat(falsePositive.getResolution()).isEqualTo("FALSE-POSITIVE");
assertThat(falsePositive.getCreationDate()).isEqualTo(issue.getCreationDate());

// user reopens the issue
assertThat(transitions(falsePositive.key())).contains("reopen");
adminIssueClient().doTransition(falsePositive.key(), "reopen");
assertThat(transitions(falsePositive.getKey())).contains("reopen");
adminIssueClient().doTransition(falsePositive.getKey(), "reopen");

Issue reopened = searchIssueByKey(issue.key());
assertThat(reopened.status()).isEqualTo("REOPENED");
assertThat(reopened.resolution()).isNull();
assertThat(reopened.creationDate()).isEqualTo(falsePositive.creationDate());
Issue reopened = issueRule.getByKey(issue.getKey());
assertThat(reopened.getStatus()).isEqualTo("REOPENED");
assertThat(reopened.hasResolution()).isFalse();
assertThat(reopened.getCreationDate()).isEqualTo(falsePositive.getCreationDate());
}

@Test
public void user_should_not_reopen_closed_issue() {
adminIssueClient().doTransition(issue.key(), "resolve");
issuesService.doTransition(new DoTransitionRequest(issue.getKey(), "resolve"));

// re-execute scan without rules -> the issue is closed
analysisWithoutIssues.run();

// user try to reopen the issue
assertThat(transitions(issue.key())).isEmpty();
assertThat(transitions(issue.getKey())).isEmpty();
}

private List<String> transitions(String issueKey) {

+ 2
- 2
server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java View File

@@ -76,8 +76,8 @@ public class InternalRubyIssueService {
@VisibleForTesting
static SearchOptions toSearchOptions(Map<String, Object> props) {
SearchOptions options = new SearchOptions();
Integer pageIndex = RubyUtils.toInteger(props.get(IssuesWsParameters.PAGE_INDEX));
Integer pageSize = RubyUtils.toInteger(props.get(IssuesWsParameters.PAGE_SIZE));
Integer pageIndex = RubyUtils.toInteger(props.get(IssuesWsParameters.PARAM_PAGE_INDEX));
Integer pageSize = RubyUtils.toInteger(props.get(IssuesWsParameters.PARAM_PAGE_SIZE));
if (pageSize != null && pageSize < 0) {
options.setLimit(SearchOptions.MAX_LIMIT);
} else {

+ 41
- 41
server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java View File

@@ -74,13 +74,13 @@ import static org.sonar.api.utils.DateUtils.parseStartingDateOrDateTime;
import static org.sonar.db.component.ComponentDtoFunctions.toProjectUuid;
import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENT_ROOTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_AFTER;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_IN_LAST;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.SINCE_LEAK_PERIOD;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_ROOTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AFTER;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_IN_LAST;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SINCE_LEAK_PERIOD;

/**
* This component is used to create an IssueQuery, in order to transform the component and component roots keys into uuid.
@@ -109,49 +109,49 @@ public class IssueQueryService {
try {

IssueQuery.Builder builder = IssueQuery.builder(userSession)
.issueKeys(RubyUtils.toStrings(params.get(IssuesWsParameters.ISSUES)))
.severities(RubyUtils.toStrings(params.get(IssuesWsParameters.SEVERITIES)))
.statuses(RubyUtils.toStrings(params.get(IssuesWsParameters.STATUSES)))
.resolutions(RubyUtils.toStrings(params.get(IssuesWsParameters.RESOLUTIONS)))
.resolved(RubyUtils.toBoolean(params.get(IssuesWsParameters.RESOLVED)))
.rules(toRules(params.get(IssuesWsParameters.RULES)))
.assignees(buildAssignees(RubyUtils.toStrings(params.get(IssuesWsParameters.ASSIGNEES))))
.languages(RubyUtils.toStrings(params.get(IssuesWsParameters.LANGUAGES)))
.tags(RubyUtils.toStrings(params.get(IssuesWsParameters.TAGS)))
.types(RubyUtils.toStrings(params.get(IssuesWsParameters.TYPES)))
.assigned(RubyUtils.toBoolean(params.get(IssuesWsParameters.ASSIGNED)))
.hideRules(RubyUtils.toBoolean(params.get(IssuesWsParameters.HIDE_RULES)))
.createdAt(RubyUtils.toDate(params.get(IssuesWsParameters.CREATED_AT)))
.createdAfter(buildCreatedAfterFromDates(RubyUtils.toDate(params.get(CREATED_AFTER)), (String) params.get(CREATED_IN_LAST)))
.createdBefore(RubyUtils.toDate(parseEndingDateOrDateTime((String) params.get(IssuesWsParameters.CREATED_BEFORE))));
.issueKeys(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_ISSUES)))
.severities(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_SEVERITIES)))
.statuses(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_STATUSES)))
.resolutions(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_RESOLUTIONS)))
.resolved(RubyUtils.toBoolean(params.get(IssuesWsParameters.PARAM_RESOLVED)))
.rules(toRules(params.get(IssuesWsParameters.PARAM_RULES)))
.assignees(buildAssignees(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_ASSIGNEES))))
.languages(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_LANGUAGES)))
.tags(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_TAGS)))
.types(RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_TYPES)))
.assigned(RubyUtils.toBoolean(params.get(IssuesWsParameters.PARAM_ASSIGNED)))
.hideRules(RubyUtils.toBoolean(params.get(IssuesWsParameters.PARAM_HIDE_RULES)))
.createdAt(RubyUtils.toDate(params.get(IssuesWsParameters.PARAM_CREATED_AT)))
.createdAfter(buildCreatedAfterFromDates(RubyUtils.toDate(params.get(PARAM_CREATED_AFTER)), (String) params.get(PARAM_CREATED_IN_LAST)))
.createdBefore(RubyUtils.toDate(parseEndingDateOrDateTime((String) params.get(IssuesWsParameters.PARAM_CREATED_BEFORE))));

Set<String> allComponentUuids = Sets.newHashSet();
boolean effectiveOnComponentOnly = mergeDeprecatedComponentParameters(session,
RubyUtils.toBoolean(params.get(IssuesWsParameters.ON_COMPONENT_ONLY)),
RubyUtils.toStrings(params.get(IssuesWsParameters.COMPONENTS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.COMPONENT_UUIDS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.COMPONENT_KEYS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.COMPONENT_ROOT_UUIDS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.COMPONENT_ROOTS)),
RubyUtils.toBoolean(params.get(IssuesWsParameters.PARAM_ON_COMPONENT_ONLY)),
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_COMPONENTS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_COMPONENT_UUIDS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_COMPONENT_KEYS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_COMPONENT_ROOT_UUIDS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_COMPONENT_ROOTS)),
allComponentUuids);

addComponentParameters(builder, session,
effectiveOnComponentOnly,
allComponentUuids,
RubyUtils.toStrings(params.get(IssuesWsParameters.PROJECT_UUIDS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_PROJECT_UUIDS)),
RubyUtils.toStrings(
ObjectUtils.defaultIfNull(
params.get(IssuesWsParameters.PROJECT_KEYS),
params.get(IssuesWsParameters.PROJECTS))),
RubyUtils.toStrings(params.get(IssuesWsParameters.MODULE_UUIDS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.DIRECTORIES)),
RubyUtils.toStrings(params.get(IssuesWsParameters.FILE_UUIDS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.AUTHORS)));
String sort = (String) params.get(IssuesWsParameters.SORT);
params.get(IssuesWsParameters.PARAM_PROJECT_KEYS),
params.get(IssuesWsParameters.PARAM_PROJECTS))),
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_MODULE_UUIDS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_DIRECTORIES)),
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_FILE_UUIDS)),
RubyUtils.toStrings(params.get(IssuesWsParameters.PARAM_AUTHORS)));
String sort = (String) params.get(IssuesWsParameters.PARAM_SORT);
if (!Strings.isNullOrEmpty(sort)) {
builder.sort(sort);
builder.asc(RubyUtils.toBoolean(params.get(IssuesWsParameters.ASC)));
builder.asc(RubyUtils.toBoolean(params.get(IssuesWsParameters.PARAM_ASC)));
}
String facetMode = (String) params.get(IssuesWsParameters.FACET_MODE);
if (!Strings.isNullOrEmpty(facetMode)) {
@@ -168,7 +168,7 @@ public class IssueQueryService {

@CheckForNull
private Date buildCreatedAfterFromDates(@Nullable Date createdAfter, @Nullable String createdInLast) {
checkArgument(createdAfter == null || createdInLast == null, format("%s and %s cannot be set simultaneously", CREATED_AFTER, CREATED_IN_LAST));
checkArgument(createdAfter == null || createdInLast == null, format("%s and %s cannot be set simultaneously", PARAM_CREATED_AFTER, PARAM_CREATED_IN_LAST));

Date actualCreatedAfter = createdAfter;
if (createdInLast != null) {
@@ -239,7 +239,7 @@ public class IssueQueryService {
return buildCreatedAfterFromDates(createdAfter, createdInLast);
}

checkRequest(createdAfter == null, "'%s' and '%s' cannot be set simultaneously", CREATED_AFTER, SINCE_LEAK_PERIOD);
checkRequest(createdAfter == null, "'%s' and '%s' cannot be set simultaneously", PARAM_CREATED_AFTER, PARAM_SINCE_LEAK_PERIOD);

checkArgument(componentUuids.size() == 1, "One and only one component must be provided when searching since leak period");
String uuid = componentUuids.iterator().next();
@@ -285,7 +285,7 @@ public class IssueQueryService {

checkArgument(atMostOneNonNullElement(components, componentUuids, componentKeys, componentRootUuids, componentRoots),
"At most one of the following parameters can be provided: %s, %s, %s, %s, %s",
COMPONENT_KEYS, COMPONENT_UUIDS, COMPONENTS, COMPONENT_ROOTS, COMPONENT_UUIDS);
PARAM_COMPONENT_KEYS, PARAM_COMPONENT_UUIDS, PARAM_COMPONENTS, PARAM_COMPONENT_ROOTS, PARAM_COMPONENT_UUIDS);

if (componentRootUuids != null) {
allComponentUuids.addAll(componentRootUuids);

+ 51
- 51
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java View File

@@ -89,25 +89,25 @@ import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
import static org.sonar.server.es.EsUtils.escapeSpecialRegexChars;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ASSIGNEES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.AUTHORS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_AT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_FACET_MODE_DEBT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_PARAM_ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_ASSIGNED_TO_ME;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FILE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.LANGUAGES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.MODULE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PROJECT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.REPORTERS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.RESOLUTIONS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.RULES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.SEVERITIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.TAGS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.TYPES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNEES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_AUTHORS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_LANGUAGES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_MODULE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_REPORTERS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RESOLUTIONS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RULES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SEVERITIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TAGS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TYPES;

/**
* The unique entry-point to interact with Elasticsearch index "issues".
@@ -118,23 +118,23 @@ public class IssueIndex extends BaseIndex {
private static final String SUBSTRING_MATCH_REGEXP = ".*%s.*";

public static final List<String> SUPPORTED_FACETS = ImmutableList.of(
SEVERITIES,
STATUSES,
RESOLUTIONS,
DEPRECATED_ACTION_PLANS,
PROJECT_UUIDS,
RULES,
ASSIGNEES,
PARAM_SEVERITIES,
PARAM_STATUSES,
PARAM_RESOLUTIONS,
DEPRECATED_PARAM_ACTION_PLANS,
PARAM_PROJECT_UUIDS,
PARAM_RULES,
PARAM_ASSIGNEES,
FACET_ASSIGNED_TO_ME,
REPORTERS,
AUTHORS,
MODULE_UUIDS,
FILE_UUIDS,
DIRECTORIES,
LANGUAGES,
TAGS,
TYPES,
CREATED_AT);
PARAM_REPORTERS,
PARAM_AUTHORS,
PARAM_MODULE_UUIDS,
PARAM_FILE_UUIDS,
PARAM_DIRECTORIES,
PARAM_LANGUAGES,
PARAM_TAGS,
PARAM_TYPES,
PARAM_CREATED_AT);

// TODO to be documented
// TODO move to Facets ?
@@ -386,39 +386,39 @@ public class IssueIndex extends BaseIndex {
StickyFacetBuilder stickyFacetBuilder = newStickyFacetBuilder(query, filters, esQuery);
// Execute Term aggregations
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
SEVERITIES, IssueIndexDefinition.FIELD_ISSUE_SEVERITY);
PARAM_SEVERITIES, IssueIndexDefinition.FIELD_ISSUE_SEVERITY);
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
STATUSES, IssueIndexDefinition.FIELD_ISSUE_STATUS);
PARAM_STATUSES, IssueIndexDefinition.FIELD_ISSUE_STATUS);
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
PROJECT_UUIDS, IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids().toArray());
PARAM_PROJECT_UUIDS, IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
MODULE_UUIDS, IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids().toArray());
PARAM_MODULE_UUIDS, IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
DIRECTORIES, IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories().toArray());
PARAM_DIRECTORIES, IssueIndexDefinition.FIELD_ISSUE_DIRECTORY_PATH, query.directories().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
FILE_UUIDS, IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.fileUuids().toArray());
PARAM_FILE_UUIDS, IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.fileUuids().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
LANGUAGES, IssueIndexDefinition.FIELD_ISSUE_LANGUAGE, query.languages().toArray());
PARAM_LANGUAGES, IssueIndexDefinition.FIELD_ISSUE_LANGUAGE, query.languages().toArray());
addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
RULES, IssueIndexDefinition.FIELD_ISSUE_RULE_KEY, query.rules().toArray());
PARAM_RULES, IssueIndexDefinition.FIELD_ISSUE_RULE_KEY, query.rules().toArray());

addSimpleStickyFacetIfNeeded(options, stickyFacetBuilder, esSearch,
AUTHORS, IssueIndexDefinition.FIELD_ISSUE_AUTHOR_LOGIN, query.authors().toArray());
PARAM_AUTHORS, IssueIndexDefinition.FIELD_ISSUE_AUTHOR_LOGIN, query.authors().toArray());

if (options.getFacets().contains(TAGS)) {
esSearch.addAggregation(stickyFacetBuilder.buildStickyFacet(IssueIndexDefinition.FIELD_ISSUE_TAGS, TAGS, query.tags().toArray()));
if (options.getFacets().contains(PARAM_TAGS)) {
esSearch.addAggregation(stickyFacetBuilder.buildStickyFacet(IssueIndexDefinition.FIELD_ISSUE_TAGS, PARAM_TAGS, query.tags().toArray()));
}
if (options.getFacets().contains(TYPES)) {
esSearch.addAggregation(stickyFacetBuilder.buildStickyFacet(IssueIndexDefinition.FIELD_ISSUE_TYPE, TYPES, query.types().toArray()));
if (options.getFacets().contains(PARAM_TYPES)) {
esSearch.addAggregation(stickyFacetBuilder.buildStickyFacet(IssueIndexDefinition.FIELD_ISSUE_TYPE, PARAM_TYPES, query.types().toArray()));
}
if (options.getFacets().contains(RESOLUTIONS)) {
if (options.getFacets().contains(PARAM_RESOLUTIONS)) {
esSearch.addAggregation(createResolutionFacet(query, filters, esQuery));
}
if (options.getFacets().contains(ASSIGNEES)) {
if (options.getFacets().contains(PARAM_ASSIGNEES)) {
esSearch.addAggregation(createAssigneesFacet(query, filters, esQuery));
}
addAssignedToMeFacetIfNeeded(esSearch, options, query, filters, esQuery);
if (options.getFacets().contains(CREATED_AT)) {
if (options.getFacets().contains(PARAM_CREATED_AT)) {
getCreatedAtFacet(query, filters, esQuery).ifPresent(esSearch::addAggregation);
}
}
@@ -481,7 +481,7 @@ public class IssueIndex extends BaseIndex {
// from GMT to server TZ
int offsetInSeconds = -system.getDefaultTimeZone().getRawOffset() / 1_000;

AggregationBuilder dateHistogram = AggregationBuilders.dateHistogram(CREATED_AT)
AggregationBuilder dateHistogram = AggregationBuilders.dateHistogram(PARAM_CREATED_AT)
.field(IssueIndexDefinition.FIELD_ISSUE_FUNC_CREATED_AT)
.interval(bucketSize)
.minDocCount(0L)
@@ -519,7 +519,7 @@ public class IssueIndex extends BaseIndex {

private static AggregationBuilder createAssigneesFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder queryBuilder) {
String fieldName = IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE;
String facetName = ASSIGNEES;
String facetName = PARAM_ASSIGNEES;

// Same as in super.stickyFacetBuilder
Map<String, QueryBuilder> assigneeFilters = Maps.newHashMap(filters);
@@ -580,7 +580,7 @@ public class IssueIndex extends BaseIndex {

private static AggregationBuilder createResolutionFacet(IssueQuery query, Map<String, QueryBuilder> filters, QueryBuilder esQuery) {
String fieldName = IssueIndexDefinition.FIELD_ISSUE_RESOLUTION;
String facetName = RESOLUTIONS;
String facetName = PARAM_RESOLUTIONS;

// Same as in super.stickyFacetBuilder
Map<String, QueryBuilder> resolutionFilters = Maps.newHashMap(filters);

+ 13
- 7
server/sonar-server/src/main/java/org/sonar/server/issue/ws/AddCommentAction.java View File

@@ -34,6 +34,7 @@ import org.sonar.server.issue.IssueFieldsSetter;
import org.sonar.server.issue.IssueFinder;
import org.sonar.server.issue.IssueUpdater;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.client.issue.AddCommentRequest;
import org.sonarqube.ws.client.issue.IssuesWsParameters;

import static com.google.common.base.Preconditions.checkArgument;
@@ -86,16 +87,21 @@ public class AddCommentAction implements IssuesWsAction {
@Override
public void handle(Request request, Response response) {
userSession.checkLoggedIn();
String issueKey = request.mandatoryParam(PARAM_ISSUE);
String commentText = request.mandatoryParam(PARAM_TEXT);
checkArgument(!isNullOrEmpty(commentText), "Cannot add empty comment to an issue");
AddCommentRequest wsRequest = toWsRequest(request);
try (DbSession dbSession = dbClient.openSession(false)) {
IssueDto issueDto = issueFinder.getByKey(dbSession, issueKey);
IssueDto issueDto = issueFinder.getByKey(dbSession, wsRequest.getIssue());
IssueChangeContext context = IssueChangeContext.createUser(new Date(system2.now()), userSession.getLogin());
DefaultIssue defaultIssue = issueDto.toDefaultIssue();
issueFieldsSetter.addComment(defaultIssue, commentText, context);
issueUpdater.saveIssue(dbSession, defaultIssue, context, commentText);
responseWriter.write(issueKey, request, response);
issueFieldsSetter.addComment(defaultIssue, wsRequest.getComment(), context);
issueUpdater.saveIssue(dbSession, defaultIssue, context, wsRequest.getComment());
responseWriter.write(defaultIssue.key(), request, response);
}
}

private static AddCommentRequest toWsRequest(Request request) {
AddCommentRequest wsRequest = new AddCommentRequest(request.mandatoryParam(PARAM_ISSUE), request.mandatoryParam(PARAM_TEXT));
checkArgument(!isNullOrEmpty(wsRequest.getComment()), "Cannot add empty comment to an issue");
return wsRequest;
}

}

+ 15
- 10
server/sonar-server/src/main/java/org/sonar/server/issue/ws/AssignAction.java View File

@@ -23,14 +23,18 @@ import org.apache.commons.lang.BooleanUtils;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.core.util.Uuids;
import org.sonar.server.issue.IssueService;
import org.sonar.server.user.UserSession;

import static com.google.common.base.Strings.emptyToNull;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_ASSIGN;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNEE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE;

public class AssignAction implements IssuesWsAction {

public static final String ASSIGN_ACTION = "assign";
private static final String DEPRECATED_PARAM_ME = "me";

private final UserSession userSession;
private final IssueService issueService;
@@ -44,36 +48,37 @@ public class AssignAction implements IssuesWsAction {

@Override
public void define(WebService.NewController controller) {
WebService.NewAction action = controller.createAction(ASSIGN_ACTION)
WebService.NewAction action = controller.createAction(ACTION_ASSIGN)
.setDescription("Assign/Unassign an issue. Requires authentication and Browse permission on project")
.setSince("3.6")
.setHandler(this)
.setPost(true);
// TODO add example of response

action.createParam("issue")
.setDescription("Key of the issue")
action.createParam(PARAM_ISSUE)
.setDescription("Issue key")
.setRequired(true)
.setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
action.createParam("assignee")
.setExampleValue(Uuids.UUID_EXAMPLE_01);
action.createParam(PARAM_ASSIGNEE)
// TODO document absent value for unassign, and "_me" for assigning to me
.setDescription("Login of the assignee")
.setExampleValue("admin");
action.createParam("me")
action.createParam(DEPRECATED_PARAM_ME)
.setDescription("(deprecated) Assign the issue to the logged-in user. Replaced by the parameter assignee=_me")
.setDeprecatedSince("5.2")
.setBooleanPossibleValues();
}

@Override
public void handle(Request request, Response response) throws Exception {
String assignee = emptyToNull(request.param("assignee"));
if ("_me".equals(assignee) || BooleanUtils.isTrue(request.paramAsBoolean("me"))) {
String assignee = emptyToNull(request.param(PARAM_ASSIGNEE));
if ("_me".equals(assignee) || BooleanUtils.isTrue(request.paramAsBoolean(DEPRECATED_PARAM_ME))) {
// Permission is currently checked by IssueService. We still
// check that user is authenticated in order to get his login.
userSession.checkLoggedIn();
assignee = userSession.getLogin();
}
String key = request.mandatoryParam("issue");
String key = request.mandatoryParam(PARAM_ISSUE);
issueService.assign(key, assignee);

responseWriter.write(key, request, response);

+ 3
- 1
server/sonar-server/src/main/java/org/sonar/server/issue/ws/AuthorsAction.java View File

@@ -28,6 +28,8 @@ import org.sonar.api.server.ws.WebService.Param;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.server.issue.IssueService;

import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_AUTHORS;

public class AuthorsAction implements IssuesWsAction {

private final IssueService service;
@@ -55,7 +57,7 @@ public class AuthorsAction implements IssuesWsAction {

@Override
public void define(WebService.NewController controller) {
NewAction action = controller.createAction("authors")
NewAction action = controller.createAction(ACTION_AUTHORS)
.setSince("5.1")
.setDescription("Search SCM accounts which match a given query")
.setResponseExample(Resources.getResource(this.getClass(), "example-authors.json"))

+ 13
- 11
server/sonar-server/src/main/java/org/sonar/server/issue/ws/ComponentTagsAction.java View File

@@ -33,15 +33,17 @@ import org.sonar.server.issue.IssueQueryService;
import org.sonar.server.issue.IssueService;
import org.sonarqube.ws.client.issue.IssuesWsParameters;

import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_COMPONENT_TAGS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_UUID;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AFTER;

/**
* List issue tags matching a given query.
* @since 5.1
*/
public class ComponentTagsAction implements IssuesWsAction {

private static final String PARAM_COMPONENT_UUID = "componentUuid";
private static final String PARAM_CREATED_AT = "createdAfter";
private static final String PARAM_PAGE_SIZE = "ps";
private final IssueService service;
private final IssueQueryService queryService;

@@ -52,7 +54,7 @@ public class ComponentTagsAction implements IssuesWsAction {

@Override
public void define(WebService.NewController controller) {
NewAction action = controller.createAction("component_tags")
NewAction action = controller.createAction(ACTION_COMPONENT_TAGS)
.setHandler(this)
.setSince("5.1")
.setInternal(true)
@@ -62,10 +64,10 @@ public class ComponentTagsAction implements IssuesWsAction {
.setDescription("A component UUID")
.setRequired(true)
.setExampleValue("7d8749e8-3070-4903-9188-bdd82933bb92");
action.createParam(PARAM_CREATED_AT)
action.createParam(PARAM_CREATED_AFTER)
.setDescription("To retrieve tags on issues created after the given date (inclusive). Format: date or datetime ISO formats")
.setExampleValue("2013-05-01 (or 2013-05-01T13:00:00+0100)");
action.createParam(PARAM_PAGE_SIZE)
action.createParam(PAGE_SIZE)
.setDescription("The maximum size of the list to return")
.setExampleValue("25")
.setDefaultValue("10");
@@ -74,13 +76,13 @@ public class ComponentTagsAction implements IssuesWsAction {
@Override
public void handle(Request request, Response response) throws Exception {
Builder<String, Object> paramBuilder = ImmutableMap.<String, Object>builder()
.put(IssuesWsParameters.COMPONENT_UUIDS, request.mandatoryParam(PARAM_COMPONENT_UUID))
.put(IssuesWsParameters.RESOLVED, false);
if (request.hasParam(PARAM_CREATED_AT)) {
paramBuilder.put(IssuesWsParameters.CREATED_AFTER, request.param(PARAM_CREATED_AT));
.put(IssuesWsParameters.PARAM_COMPONENT_UUIDS, request.mandatoryParam(PARAM_COMPONENT_UUID))
.put(IssuesWsParameters.PARAM_RESOLVED, false);
if (request.hasParam(PARAM_CREATED_AFTER)) {
paramBuilder.put(PARAM_CREATED_AFTER, request.param(PARAM_CREATED_AFTER));
}
IssueQuery query = queryService.createFromMap(paramBuilder.build());
int pageSize = request.mandatoryParamAsInt(PARAM_PAGE_SIZE);
int pageSize = request.mandatoryParamAsInt(PAGE_SIZE);
JsonWriter json = response.newJsonWriter().beginObject().name("tags").beginArray();
for (Map.Entry<String, Long> tag : service.listTagsForComponent(query, pageSize).entrySet()) {
json.beginObject()

+ 12
- 9
server/sonar-server/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java View File

@@ -26,6 +26,7 @@ import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.IssueChangeContext;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.issue.IssueDto;
@@ -34,9 +35,11 @@ import org.sonar.server.issue.IssueUpdater;
import org.sonar.server.issue.TransitionService;
import org.sonar.server.user.UserSession;

public class DoTransitionAction implements IssuesWsAction {
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_DO_TRANSITION;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TRANSITION;

public static final String ACTION = "do_transition";
public class DoTransitionAction implements IssuesWsAction {

private final DbClient dbClient;
private final UserSession userSession;
@@ -57,18 +60,18 @@ public class DoTransitionAction implements IssuesWsAction {

@Override
public void define(WebService.NewController controller) {
WebService.NewAction action = controller.createAction(ACTION)
WebService.NewAction action = controller.createAction(ACTION_DO_TRANSITION)
.setDescription("Do workflow transition on an issue. Requires authentication and Browse permission on project.<br/>" +
"The transitions '" + DefaultTransitions.WONT_FIX + "' and '" + DefaultTransitions.FALSE_POSITIVE + "' require the permission 'Administer Issues'.")
.setSince("3.6")
.setHandler(this)
.setPost(true);

action.createParam("issue")
.setDescription("Key of the issue")
action.createParam(PARAM_ISSUE)
.setDescription("Issue key")
.setRequired(true)
.setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
action.createParam("transition")
.setExampleValue(Uuids.UUID_EXAMPLE_01);
action.createParam(PARAM_TRANSITION)
.setDescription("Transition")
.setRequired(true)
.setPossibleValues(DefaultTransitions.ALL);
@@ -77,10 +80,10 @@ public class DoTransitionAction implements IssuesWsAction {
@Override
public void handle(Request request, Response response) {
userSession.checkLoggedIn();
String issue = request.mandatoryParam("issue");
String issue = request.mandatoryParam(PARAM_ISSUE);
try (DbSession dbSession = dbClient.openSession(false)) {
IssueDto issueDto = issueFinder.getByKey(dbSession, issue);
doTransition(dbSession, issueDto.toDefaultIssue(), request.mandatoryParam("transition"));
doTransition(dbSession, issueDto.toDefaultIssue(), request.mandatoryParam(PARAM_TRANSITION));
responseWriter.write(issue, request, response);
}
}

+ 116
- 116
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java View File

@@ -56,49 +56,49 @@ import static org.sonar.api.utils.Paging.forPageIndex;
import static org.sonar.server.es.SearchOptions.MAX_LIMIT;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ADDITIONAL_FIELDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ASC;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ASSIGNED;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ASSIGNEES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.AUTHORS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENT_ROOTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENT_ROOT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_AFTER;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_AT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_BEFORE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_IN_LAST;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SEARCH;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_FACET_MODE_DEBT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_PARAM_ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_ASSIGNED_TO_ME;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_COUNT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FILE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ISSUES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.LANGUAGES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.MODULE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ON_COMPONENT_ONLY;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PLANNED;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PROJECTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PROJECT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PROJECT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.RESOLUTIONS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.RESOLVED;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.RULES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.SEVERITIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.SINCE_LEAK_PERIOD;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.TAGS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.TYPES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ADDITIONAL_FIELDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASC;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNED;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNEES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_AUTHORS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_ROOTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_ROOT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AFTER;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_BEFORE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_IN_LAST;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_LANGUAGES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_MODULE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ON_COMPONENT_ONLY;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PLANNED;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RESOLUTIONS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RESOLVED;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RULES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SEVERITIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SINCE_LEAK_PERIOD;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TAGS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TYPES;

public class SearchAction implements IssuesWsAction {

private static final String INTERNAL_PARAMETER_DISCLAIMER = "This parameter is mostly used by the Issues page, please prefer usage of the componentKeys parameter. ";
public static final String SEARCH_ACTION = "search";

private final UserSession userSession;
private final IssueIndex issueIndex;
@@ -118,7 +118,7 @@ public class SearchAction implements IssuesWsAction {
@Override
public void define(WebService.NewController controller) {
WebService.NewAction action = controller
.createAction(SEARCH_ACTION)
.createAction(ACTION_SEARCH)
.setHandler(this)
.setDescription(
"Search for issues. Requires Browse permission on project(s).<br>" +
@@ -126,7 +126,7 @@ public class SearchAction implements IssuesWsAction {
"Since 5.5, response field 'debt' has been renamed to 'effort'.<br>" +
"Since 5.5, response field 'actionPlan' has been removed.<br>" +
"Since 5.5, response field 'reporter' has been removed, as manual issue feature has been dropped.",
COMPONENT_KEYS, COMPONENT_UUIDS, COMPONENTS, COMPONENT_ROOT_UUIDS, COMPONENT_ROOTS)
PARAM_COMPONENT_KEYS, PARAM_COMPONENT_UUIDS, PARAM_COMPONENTS, PARAM_COMPONENT_ROOT_UUIDS, PARAM_COMPONENT_ROOTS)
.setSince("3.6")
.setResponseExample(getClass().getResource("example-search.json"));

@@ -142,45 +142,45 @@ public class SearchAction implements IssuesWsAction {
"Since 5.5, 'debt' mode is deprecated and replaced by 'effort'")
.setPossibleValues(FACET_MODE_COUNT, FACET_MODE_EFFORT, DEPRECATED_FACET_MODE_DEBT);
action.addSortParams(IssueQuery.SORTS, null, true);
action.createParam(ADDITIONAL_FIELDS)
action.createParam(PARAM_ADDITIONAL_FIELDS)
.setSince("5.2")
.setDescription("Comma-separated list of the optional fields to be returned in response. Action plans are dropped in 5.5, it is not returned in the response.")
.setPossibleValues(SearchAdditionalField.possibleValues());
addComponentRelatedParams(action);
action.createParam(ISSUES)
action.createParam(PARAM_ISSUES)
.setDescription("Comma-separated list of issue keys")
.setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
action.createParam(SEVERITIES)
action.createParam(PARAM_SEVERITIES)
.setDescription("Comma-separated list of severities")
.setExampleValue(Severity.BLOCKER + "," + Severity.CRITICAL)
.setPossibleValues(Severity.ALL);
action.createParam(STATUSES)
action.createParam(PARAM_STATUSES)
.setDescription("Comma-separated list of statuses")
.setExampleValue(Issue.STATUS_OPEN + "," + Issue.STATUS_REOPENED)
.setPossibleValues(Issue.STATUSES);
action.createParam(RESOLUTIONS)
action.createParam(PARAM_RESOLUTIONS)
.setDescription("Comma-separated list of resolutions")
.setExampleValue(Issue.RESOLUTION_FIXED + "," + Issue.RESOLUTION_REMOVED)
.setPossibleValues(Issue.RESOLUTIONS);
action.createParam(RESOLVED)
action.createParam(PARAM_RESOLVED)
.setDescription("To match resolved or unresolved issues")
.setBooleanPossibleValues();
action.createParam(RULES)
action.createParam(PARAM_RULES)
.setDescription("Comma-separated list of coding rule keys. Format is &lt;repository&gt;:&lt;rule&gt;")
.setExampleValue("squid:AvoidCycles");
action.createParam(TAGS)
action.createParam(PARAM_TAGS)
.setDescription("Comma-separated list of tags.")
.setExampleValue("security,convention");
action.createParam(TYPES)
action.createParam(PARAM_TYPES)
.setDescription("Comma-separated list of types.")
.setSince("5.5")
.setPossibleValues(RuleType.values())
.setExampleValue(format("%s,%s", RuleType.CODE_SMELL, RuleType.BUG));
action.createParam(DEPRECATED_ACTION_PLANS)
action.createParam(DEPRECATED_PARAM_ACTION_PLANS)
.setDescription("Action plans are dropped in 5.5. This parameter has no effect. Comma-separated list of action plan keys (not names)")
.setDeprecatedSince("5.5")
.setExampleValue("3f19de90-1521-4482-a737-a311758ff513");
action.createParam(PLANNED)
action.createParam(PARAM_PLANNED)
.setDescription("Since 5.5 this parameter is no more used, as action plan feature has been dropped")
.setDeprecatedSince("5.5")
.setBooleanPossibleValues();
@@ -188,33 +188,33 @@ public class SearchAction implements IssuesWsAction {
.setDescription("Since 5.5 this parameter is no more used, as manual issue feature has been dropped")
.setExampleValue("admin")
.setDeprecatedSince("5.5");
action.createParam(AUTHORS)
action.createParam(PARAM_AUTHORS)
.setDescription("Comma-separated list of SCM accounts")
.setExampleValue("torvalds@linux-foundation.org");
action.createParam(ASSIGNEES)
action.createParam(PARAM_ASSIGNEES)
.setDescription("Comma-separated list of assignee logins. The value '__me__' can be used as a placeholder for user who performs the request")
.setExampleValue("admin,usera,__me__");
action.createParam(ASSIGNED)
action.createParam(PARAM_ASSIGNED)
.setDescription("To retrieve assigned or unassigned issues")
.setBooleanPossibleValues();
action.createParam(LANGUAGES)
action.createParam(PARAM_LANGUAGES)
.setDescription("Comma-separated list of languages. Available since 4.4")
.setExampleValue("java,js");
action.createParam(CREATED_AT)
action.createParam(PARAM_CREATED_AT)
.setDescription("To retrieve issues created in a specific analysis, identified by an ISO-formatted datetime stamp.")
.setExampleValue("2013-05-01T13:00:00+0100");
action.createParam(CREATED_AFTER)
action.createParam(PARAM_CREATED_AFTER)
.setDescription("To retrieve issues created after the given date (inclusive). Format: date or datetime ISO formats. If this parameter is set, createdSince must not be set")
.setExampleValue("2013-05-01 (or 2013-05-01T13:00:00+0100)");
action.createParam(CREATED_BEFORE)
action.createParam(PARAM_CREATED_BEFORE)
.setDescription("To retrieve issues created before the given date (exclusive). Format: date or datetime ISO formats")
.setExampleValue("2013-05-01 (or 2013-05-01T13:00:00+0100)");
action.createParam(CREATED_IN_LAST)
action.createParam(PARAM_CREATED_IN_LAST)
.setDescription("To retrieve issues created during a time span before the current time (exclusive). " +
"Accepted units are 'y' for year, 'm' for month, 'w' for week and 'd' for day. " +
"If this parameter is set, createdAfter must not be set")
.setExampleValue("1m2w (1 month 2 weeks)");
action.createParam(SINCE_LEAK_PERIOD)
action.createParam(PARAM_SINCE_LEAK_PERIOD)
.setDescription("To retrieve issues created since the leak period.<br>" +
"If this parameter is set to a truthy value, createdAfter must not be set and one component id or key must be provided.")
.setBooleanPossibleValues()
@@ -222,7 +222,7 @@ public class SearchAction implements IssuesWsAction {
}

private static void addComponentRelatedParams(WebService.NewAction action) {
action.createParam(ON_COMPONENT_ONLY)
action.createParam(PARAM_ON_COMPONENT_ONLY)
.setDescription("Return only issues at a component's level, not on its descendants (modules, directories, files, etc). " +
"This parameter is only considered when componentKeys or componentUuids is set. " +
"Using the deprecated componentRoots or componentRootUuids parameters will set this parameter to false. " +
@@ -230,54 +230,54 @@ public class SearchAction implements IssuesWsAction {
.setBooleanPossibleValues()
.setDefaultValue("false");

action.createParam(COMPONENT_KEYS)
action.createParam(PARAM_COMPONENT_KEYS)
.setDescription("To retrieve issues associated to a specific list of components sub-components (comma-separated list of component keys). " +
"A component can be a view, developer, project, module, directory or file.")
.setExampleValue(KEY_PROJECT_EXAMPLE_001);
action.createParam(COMPONENTS)
action.createParam(PARAM_COMPONENTS)
.setDeprecatedSince("5.1")
.setDescription("If used, will have the same meaning as componentKeys AND onComponentOnly=true.");
action.createParam(COMPONENT_UUIDS)
action.createParam(PARAM_COMPONENT_UUIDS)
.setDescription("To retrieve issues associated to a specific list of components their sub-components (comma-separated list of component UUIDs). " +
INTERNAL_PARAMETER_DISCLAIMER +
"A component can be a project, module, directory or file.")
.setExampleValue("584a89f2-8037-4f7b-b82c-8b45d2d63fb2");
action.createParam(COMPONENT_ROOTS)
action.createParam(PARAM_COMPONENT_ROOTS)
.setDeprecatedSince("5.1")
.setDescription("If used, will have the same meaning as componentKeys AND onComponentOnly=false.");
action.createParam(COMPONENT_ROOT_UUIDS)
action.createParam(PARAM_COMPONENT_ROOT_UUIDS)
.setDeprecatedSince("5.1")
.setDescription("If used, will have the same meaning as componentUuids AND onComponentOnly=false.");

action.createParam(PROJECTS)
action.createParam(PARAM_PROJECTS)
.setDeprecatedSince("5.1")
.setDescription("See projectKeys");
action.createParam(PROJECT_KEYS)
action.createParam(PARAM_PROJECT_KEYS)
.setDescription("To retrieve issues associated to a specific list of projects (comma-separated list of project keys). " +
INTERNAL_PARAMETER_DISCLAIMER +
"If this parameter is set, projectUuids must not be set.")
.setDeprecatedKey(PROJECTS)
.setDeprecatedKey(PARAM_PROJECTS)
.setExampleValue(KEY_PROJECT_EXAMPLE_001);
action.createParam(PROJECT_UUIDS)
action.createParam(PARAM_PROJECT_UUIDS)
.setDescription("To retrieve issues associated to a specific list of projects (comma-separated list of project UUIDs). " +
INTERNAL_PARAMETER_DISCLAIMER +
"Views are not supported. If this parameter is set, projectKeys must not be set.")
.setExampleValue("7d8749e8-3070-4903-9188-bdd82933bb92");

action.createParam(MODULE_UUIDS)
action.createParam(PARAM_MODULE_UUIDS)
.setDescription("To retrieve issues associated to a specific list of modules (comma-separated list of module UUIDs). " +
INTERNAL_PARAMETER_DISCLAIMER +
"Views are not supported. If this parameter is set, moduleKeys must not be set.")
.setExampleValue("7d8749e8-3070-4903-9188-bdd82933bb92");

action.createParam(DIRECTORIES)
action.createParam(PARAM_DIRECTORIES)
.setDescription("To retrieve issues associated to a specific list of directories (comma-separated list of directory paths). " +
"This parameter is only meaningful when a module is selected. " +
INTERNAL_PARAMETER_DISCLAIMER)
.setSince("5.1")
.setExampleValue("src/main/java/org/sonar/server/");

action.createParam(FILE_UUIDS)
action.createParam(PARAM_FILE_UUIDS)
.setDescription("To retrieve issues associated to a specific list of files (comma-separated list of file UUIDs). " +
INTERNAL_PARAMETER_DISCLAIMER)
.setExampleValue("bdd82933-3070-4903-9188-7d8749e8bb92");
@@ -350,10 +350,10 @@ public class SearchAction implements IssuesWsAction {
}

private void completeFacets(Facets facets, SearchWsRequest request, Request wsRequest) {
addMandatoryValuesToFacet(facets, SEVERITIES, Severity.ALL);
addMandatoryValuesToFacet(facets, STATUSES, Issue.STATUSES);
addMandatoryValuesToFacet(facets, RESOLUTIONS, concat(singletonList(""), Issue.RESOLUTIONS));
addMandatoryValuesToFacet(facets, PROJECT_UUIDS, request.getProjectUuids());
addMandatoryValuesToFacet(facets, PARAM_SEVERITIES, Severity.ALL);
addMandatoryValuesToFacet(facets, PARAM_STATUSES, Issue.STATUSES);
addMandatoryValuesToFacet(facets, PARAM_RESOLUTIONS, concat(singletonList(""), Issue.RESOLUTIONS));
addMandatoryValuesToFacet(facets, PARAM_PROJECT_UUIDS, request.getProjectUuids());

List<String> assignees = Lists.newArrayList("");
List<String> assigneesFromRequest = request.getAssignees();
@@ -361,13 +361,13 @@ public class SearchAction implements IssuesWsAction {
assignees.addAll(assigneesFromRequest);
assignees.remove(IssueQueryService.LOGIN_MYSELF);
}
addMandatoryValuesToFacet(facets, ASSIGNEES, assignees);
addMandatoryValuesToFacet(facets, PARAM_ASSIGNEES, assignees);
addMandatoryValuesToFacet(facets, FACET_ASSIGNED_TO_ME, singletonList(userSession.getLogin()));
addMandatoryValuesToFacet(facets, RULES, request.getRules());
addMandatoryValuesToFacet(facets, LANGUAGES, request.getLanguages());
addMandatoryValuesToFacet(facets, TAGS, request.getTags());
addMandatoryValuesToFacet(facets, TYPES, RuleType.names());
addMandatoryValuesToFacet(facets, COMPONENT_UUIDS, request.getComponentUuids());
addMandatoryValuesToFacet(facets, PARAM_RULES, request.getRules());
addMandatoryValuesToFacet(facets, PARAM_LANGUAGES, request.getLanguages());
addMandatoryValuesToFacet(facets, PARAM_TAGS, request.getTags());
addMandatoryValuesToFacet(facets, PARAM_TYPES, RuleType.names());
addMandatoryValuesToFacet(facets, PARAM_COMPONENT_UUIDS, request.getComponentUuids());

for (String facetName : request.getFacets()) {
LinkedHashMap<String, Long> buckets = facets.get(facetName);
@@ -405,15 +405,15 @@ public class SearchAction implements IssuesWsAction {
}

private void collectFacets(SearchResponseLoader.Collector collector, Facets facets) {
Set<String> facetRules = facets.getBucketKeys(RULES);
Set<String> facetRules = facets.getBucketKeys(PARAM_RULES);
if (facetRules != null) {
collector.addAll(SearchAdditionalField.RULES, from(facetRules).transform(RuleKeyFunctions.stringToRuleKey()));
}
collector.addProjectUuids(facets.getBucketKeys(PROJECT_UUIDS));
collector.addComponentUuids(facets.getBucketKeys(COMPONENT_UUIDS));
collector.addComponentUuids(facets.getBucketKeys(FILE_UUIDS));
collector.addComponentUuids(facets.getBucketKeys(MODULE_UUIDS));
collector.addAll(SearchAdditionalField.USERS, facets.getBucketKeys(ASSIGNEES));
collector.addProjectUuids(facets.getBucketKeys(PARAM_PROJECT_UUIDS));
collector.addComponentUuids(facets.getBucketKeys(PARAM_COMPONENT_UUIDS));
collector.addComponentUuids(facets.getBucketKeys(PARAM_FILE_UUIDS));
collector.addComponentUuids(facets.getBucketKeys(PARAM_MODULE_UUIDS));
collector.addAll(SearchAdditionalField.USERS, facets.getBucketKeys(PARAM_ASSIGNEES));
}

private void collectRequestParams(SearchResponseLoader.Collector collector, SearchWsRequest request) {
@@ -426,42 +426,42 @@ public class SearchAction implements IssuesWsAction {

private static SearchWsRequest toSearchWsRequest(Request request) {
return new SearchWsRequest()
.setAdditionalFields(request.paramAsStrings(ADDITIONAL_FIELDS))
.setAsc(request.paramAsBoolean(ASC))
.setAssigned(request.paramAsBoolean(ASSIGNED))
.setAssignees(request.paramAsStrings(ASSIGNEES))
.setAuthors(request.paramAsStrings(AUTHORS))
.setComponentKeys(request.paramAsStrings(COMPONENT_KEYS))
.setComponentRootUuids(request.paramAsStrings(COMPONENT_ROOT_UUIDS))
.setComponentRoots(request.paramAsStrings(COMPONENT_ROOTS))
.setComponentUuids(request.paramAsStrings(COMPONENT_UUIDS))
.setComponents(request.paramAsStrings(COMPONENTS))
.setCreatedAfter(request.param(CREATED_AFTER))
.setCreatedAt(request.param(CREATED_AT))
.setCreatedBefore(request.param(CREATED_BEFORE))
.setCreatedInLast(request.param(CREATED_IN_LAST))
.setDirectories(request.paramAsStrings(DIRECTORIES))
.setAdditionalFields(request.paramAsStrings(PARAM_ADDITIONAL_FIELDS))
.setAsc(request.paramAsBoolean(PARAM_ASC))
.setAssigned(request.paramAsBoolean(PARAM_ASSIGNED))
.setAssignees(request.paramAsStrings(PARAM_ASSIGNEES))
.setAuthors(request.paramAsStrings(PARAM_AUTHORS))
.setComponentKeys(request.paramAsStrings(PARAM_COMPONENT_KEYS))
.setComponentRootUuids(request.paramAsStrings(PARAM_COMPONENT_ROOT_UUIDS))
.setComponentRoots(request.paramAsStrings(PARAM_COMPONENT_ROOTS))
.setComponentUuids(request.paramAsStrings(PARAM_COMPONENT_UUIDS))
.setComponents(request.paramAsStrings(PARAM_COMPONENTS))
.setCreatedAfter(request.param(PARAM_CREATED_AFTER))
.setCreatedAt(request.param(PARAM_CREATED_AT))
.setCreatedBefore(request.param(PARAM_CREATED_BEFORE))
.setCreatedInLast(request.param(PARAM_CREATED_IN_LAST))
.setDirectories(request.paramAsStrings(PARAM_DIRECTORIES))
.setFacetMode(request.mandatoryParam(FACET_MODE))
.setFacets(request.paramAsStrings(Param.FACETS))
.setFileUuids(request.paramAsStrings(FILE_UUIDS))
.setIssues(request.paramAsStrings(ISSUES))
.setLanguages(request.paramAsStrings(LANGUAGES))
.setModuleUuids(request.paramAsStrings(MODULE_UUIDS))
.setOnComponentOnly(request.paramAsBoolean(ON_COMPONENT_ONLY))
.setFileUuids(request.paramAsStrings(PARAM_FILE_UUIDS))
.setIssues(request.paramAsStrings(PARAM_ISSUES))
.setLanguages(request.paramAsStrings(PARAM_LANGUAGES))
.setModuleUuids(request.paramAsStrings(PARAM_MODULE_UUIDS))
.setOnComponentOnly(request.paramAsBoolean(PARAM_ON_COMPONENT_ONLY))
.setPage(request.mandatoryParamAsInt(Param.PAGE))
.setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE))
.setProjectKeys(request.paramAsStrings(PROJECT_KEYS))
.setProjectUuids(request.paramAsStrings(PROJECT_UUIDS))
.setProjects(request.paramAsStrings(PROJECTS))
.setResolutions(request.paramAsStrings(RESOLUTIONS))
.setResolved(request.paramAsBoolean(RESOLVED))
.setRules(request.paramAsStrings(RULES))
.setSinceLeakPeriod(request.mandatoryParamAsBoolean(SINCE_LEAK_PERIOD))
.setProjectKeys(request.paramAsStrings(PARAM_PROJECT_KEYS))
.setProjectUuids(request.paramAsStrings(PARAM_PROJECT_UUIDS))
.setProjects(request.paramAsStrings(PARAM_PROJECTS))
.setResolutions(request.paramAsStrings(PARAM_RESOLUTIONS))
.setResolved(request.paramAsBoolean(PARAM_RESOLVED))
.setRules(request.paramAsStrings(PARAM_RULES))
.setSinceLeakPeriod(request.mandatoryParamAsBoolean(PARAM_SINCE_LEAK_PERIOD))
.setSort(request.param(Param.SORT))
.setSeverities(request.paramAsStrings(SEVERITIES))
.setStatuses(request.paramAsStrings(STATUSES))
.setTags(request.paramAsStrings(TAGS))
.setTypes(request.paramAsStrings(TYPES));
.setSeverities(request.paramAsStrings(PARAM_SEVERITIES))
.setStatuses(request.paramAsStrings(PARAM_STATUSES))
.setTags(request.paramAsStrings(PARAM_TAGS))
.setTypes(request.paramAsStrings(PARAM_TYPES));
}

private enum IssueDocToKey implements Function<IssueDoc, String> {

+ 12
- 9
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SetSeverityAction.java View File

@@ -23,11 +23,14 @@ import org.sonar.api.rule.Severity;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.core.util.Uuids;
import org.sonar.server.issue.IssueService;

public class SetSeverityAction implements IssuesWsAction {
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SET_SEVERITY;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SEVERITY;

public static final String ACTION = "set_severity";
public class SetSeverityAction implements IssuesWsAction {

private final IssueService issueService;
private final OperationResponseWriter responseWriter;
@@ -39,17 +42,17 @@ public class SetSeverityAction implements IssuesWsAction {

@Override
public void define(WebService.NewController controller) {
WebService.NewAction action = controller.createAction(ACTION)
WebService.NewAction action = controller.createAction(ACTION_SET_SEVERITY)
.setDescription("Change severity. Requires authentication and Browse permission on project")
.setSince("3.6")
.setHandler(this)
.setPost(true);

action.createParam("issue")
.setDescription("Key of the issue")
action.createParam(PARAM_ISSUE)
.setDescription("Issue key")
.setRequired(true)
.setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
action.createParam("severity")
.setExampleValue(Uuids.UUID_EXAMPLE_01);
action.createParam(PARAM_SEVERITY)
.setDescription("New severity")
.setRequired(true)
.setPossibleValues(Severity.ALL);
@@ -57,8 +60,8 @@ public class SetSeverityAction implements IssuesWsAction {

@Override
public void handle(Request request, Response response) throws Exception {
String key = request.mandatoryParam("issue");
issueService.setSeverity(key, request.mandatoryParam("severity"));
String key = request.mandatoryParam(PARAM_ISSUE);
issueService.setSeverity(key, request.mandatoryParam(PARAM_SEVERITY));

responseWriter.write(key, request, response);
}

+ 18
- 10
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SetTagsAction.java View File

@@ -20,16 +20,20 @@
package org.sonar.server.issue.ws;

import com.google.common.base.MoreObjects;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.NewAction;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.util.Uuids;
import org.sonar.server.issue.IssueService;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SET_TAGS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TAGS;

/**
* Set tags on an issue
@@ -44,24 +48,28 @@ public class SetTagsAction implements IssuesWsAction {

@Override
public void define(WebService.NewController controller) {
NewAction action = controller.createAction("set_tags")
NewAction action = controller.createAction(ACTION_SET_TAGS)
.setHandler(this)
.setPost(true)
.setSince("5.1")
.setDescription("Set tags on an issue. Requires authentication and Browse permission on project");
action.createParam("key")
.setDescription("Set tags on an issue. <br/>" +
"Requires authentication and Browse permission on project<br/>" +
"Since 6.3, the parameter 'key' has been replaced by '%s'", PARAM_ISSUE);
action.createParam(PARAM_ISSUE)
.setDescription("Issue key")
.setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef")
.setSince("6.3")
.setDeprecatedKey("key")
.setExampleValue(Uuids.UUID_EXAMPLE_01)
.setRequired(true);
action.createParam("tags")
action.createParam(PARAM_TAGS)
.setDescription("Comma-separated list of tags. All tags are removed if parameter is empty or not set.")
.setExampleValue("security,cwe,misra-c");
}

@Override
public void handle(Request request, Response response) throws Exception {
String key = request.mandatoryParam("key");
List<String> tags = MoreObjects.firstNonNull(request.paramAsStrings("tags"), Collections.<String>emptyList());
String key = request.mandatoryParam(PARAM_ISSUE);
List<String> tags = MoreObjects.firstNonNull(request.paramAsStrings(PARAM_TAGS), Collections.<String>emptyList());
Collection<String> resultTags = service.setTags(key, tags);
JsonWriter json = response.newJsonWriter().beginObject().name("tags").beginArray();
for (String tag : resultTags) {

+ 10
- 8
server/sonar-server/src/main/java/org/sonar/server/issue/ws/SetTypeAction.java View File

@@ -26,9 +26,11 @@ import org.sonar.api.server.ws.WebService;
import org.sonar.core.util.Uuids;
import org.sonar.server.issue.IssueService;

public class SetTypeAction implements IssuesWsAction {
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SET_TYPE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TYPE;

public static final String ACTION = "set_type";
public class SetTypeAction implements IssuesWsAction {

private final IssueService issueService;
private final OperationResponseWriter responseWriter;
@@ -40,17 +42,17 @@ public class SetTypeAction implements IssuesWsAction {

@Override
public void define(WebService.NewController controller) {
WebService.NewAction action = controller.createAction(ACTION)
WebService.NewAction action = controller.createAction(ACTION_SET_TYPE)
.setDescription("Change type of issue, for instance from 'code smell' to 'bug'. Requires authentication and Browse permission on project.")
.setSince("5.5")
.setHandler(this)
.setPost(true);

action.createParam("issue")
.setDescription("Key of the issue")
action.createParam(PARAM_ISSUE)
.setDescription("Issue key")
.setRequired(true)
.setExampleValue(Uuids.UUID_EXAMPLE_01);
action.createParam("type")
action.createParam(PARAM_TYPE)
.setDescription("New type")
.setRequired(true)
.setPossibleValues(RuleType.names());
@@ -58,8 +60,8 @@ public class SetTypeAction implements IssuesWsAction {

@Override
public void handle(Request request, Response response) throws Exception {
String key = request.mandatoryParam("issue");
issueService.setType(key, RuleType.valueOf(request.mandatoryParam("type")));
String key = request.mandatoryParam(PARAM_ISSUE);
issueService.setType(key, RuleType.valueOf(request.mandatoryParam(PARAM_TYPE)));

responseWriter.write(key, request, response);
}

+ 2
- 3
server/sonar-server/src/test/java/org/sonar/server/issue/ws/ComponentTagsActionTest.java View File

@@ -20,6 +20,7 @@
package org.sonar.server.issue.ws;

import com.google.common.collect.ImmutableMap;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -33,8 +34,6 @@ import org.sonar.server.issue.IssueQueryService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.ws.WsTester;

import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -112,7 +111,7 @@ public class ComponentTagsActionTest {
}

@Test
public void should_return_tag_list_wuth_created_after() throws Exception {
public void should_return_tag_list_with_created_after() throws Exception {
Map<String, Long> tags = ImmutableMap.<String, Long>builder()
.put("convention", 2771L)
.put("brain-overload", 998L)

+ 76
- 75
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionComponentsMediumTest.java View File

@@ -69,6 +69,7 @@ import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newModuleDto;
import static org.sonar.db.component.SnapshotTesting.newAnalysis;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SEARCH;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CONTROLLER_ISSUES;

public class SearchActionComponentsMediumTest {
@@ -123,7 +124,7 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION).execute();
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH).execute();
result.assertJson(this.getClass(), "issues_on_different_projects.json");
}

@@ -167,23 +168,23 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.PROJECT_UUIDS, project.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_PROJECT_UUIDS, project.uuid())
.execute()
.assertJson(this.getClass(), "search_by_project_uuid.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.PROJECT_UUIDS, "unknown")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_PROJECT_UUIDS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, project.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, project.uuid())
.execute()
.assertJson(this.getClass(), "search_by_project_uuid.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, "unknown")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");
}
@@ -209,9 +210,9 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, project.uuid())
.setParam(IssuesWsParameters.SINCE_LEAK_PERIOD, "true")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, project.uuid())
.setParam(IssuesWsParameters.PARAM_SINCE_LEAK_PERIOD, "true")
.execute()
.assertJson(this.getClass(), "search_since_leak_period.json");
}
@@ -237,10 +238,10 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, project.uuid())
.setParam(IssuesWsParameters.FILE_UUIDS, file.uuid())
.setParam(IssuesWsParameters.SINCE_LEAK_PERIOD, "true")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, project.uuid())
.setParam(IssuesWsParameters.PARAM_FILE_UUIDS, file.uuid())
.setParam(IssuesWsParameters.PARAM_SINCE_LEAK_PERIOD, "true")
.execute()
.assertJson(this.getClass(), "search_since_leak_period.json");
}
@@ -264,8 +265,8 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.PROJECT_UUIDS, project1.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_PROJECT_UUIDS, project1.uuid())
.setParam(WebService.Param.FACETS, "projectUuids")
.execute()
.assertJson(this.getClass(), "display_sticky_project_facet.json");
@@ -281,23 +282,23 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.FILE_UUIDS, file.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_FILE_UUIDS, file.uuid())
.execute()
.assertJson(this.getClass(), "search_by_file_uuid.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.FILE_UUIDS, "unknown")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_FILE_UUIDS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, file.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, file.uuid())
.execute()
.assertJson(this.getClass(), "search_by_file_uuid.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, "unknown")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");
}
@@ -315,13 +316,13 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENTS, file.key())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENTS, file.key())
.execute()
.assertJson(this.getClass(), "search_by_file_key.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENTS, unitTest.key())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENTS, unitTest.key())
.execute()
.assertJson(this.getClass(), "search_by_test_key.json");
}
@@ -340,9 +341,9 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, project.uuid())
.setParam(IssuesWsParameters.FILE_UUIDS, file1.uuid() + "," + file3.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, project.uuid())
.setParam(IssuesWsParameters.PARAM_FILE_UUIDS, file1.uuid() + "," + file3.uuid())
.setParam(WebService.Param.FACETS, "fileUuids")
.execute()
.assertJson(this.getClass(), "display_file_facet.json");
@@ -359,23 +360,23 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, directory.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, directory.uuid())
.execute()
.assertJson(this.getClass(), "search_by_file_uuid.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, "unknown")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.DIRECTORIES, "src/main/java/dir")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_DIRECTORIES, "src/main/java/dir")
.execute()
.assertJson(this.getClass(), "search_by_file_uuid.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.DIRECTORIES, "src/main/java")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_DIRECTORIES, "src/main/java")
.execute()
.assertJson(this.getClass(), "no_issue.json");
}
@@ -397,35 +398,35 @@ public class SearchActionComponentsMediumTest {

tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, directory1.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, directory1.uuid())
.execute()
.assertJson(this.getClass(), "search_by_directory_uuid.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, directory2.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, directory2.uuid())
.execute()
.assertJson(this.getClass(), "no_issue.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.MODULE_UUIDS, module1.uuid())
.setParam(IssuesWsParameters.DIRECTORIES, "src/main/java/dir")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_MODULE_UUIDS, module1.uuid())
.setParam(IssuesWsParameters.PARAM_DIRECTORIES, "src/main/java/dir")
.execute()
.assertJson(this.getClass(), "search_by_directory_uuid.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.MODULE_UUIDS, module2.uuid())
.setParam(IssuesWsParameters.DIRECTORIES, "src/main/java/dir")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_MODULE_UUIDS, module2.uuid())
.setParam(IssuesWsParameters.PARAM_DIRECTORIES, "src/main/java/dir")
.execute()
.assertJson(this.getClass(), "no_issue.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.DIRECTORIES, "src/main/java/dir")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_DIRECTORIES, "src/main/java/dir")
.execute()
.assertJson(this.getClass(), "search_by_directory_uuid.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.DIRECTORIES, "src/main/java")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_DIRECTORIES, "src/main/java")
.execute()
.assertJson(this.getClass(), "no_issue.json");
}
@@ -447,9 +448,9 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, module.uuid())
.setParam(IssuesWsParameters.MODULE_UUIDS, subModule1.uuid() + "," + subModule3.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, module.uuid())
.setParam(IssuesWsParameters.PARAM_MODULE_UUIDS, subModule1.uuid() + "," + subModule3.uuid())
.setParam(WebService.Param.FACETS, "moduleUuids")
.execute()
.assertJson(this.getClass(), "display_module_facet.json");
@@ -467,7 +468,7 @@ public class SearchActionComponentsMediumTest {
tester.get(IssueIndexer.class).indexAll();

userSessionRule.login("john");
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam("resolved", "false")
.setParam(WebService.Param.FACETS, "directories")
.execute();
@@ -487,8 +488,8 @@ public class SearchActionComponentsMediumTest {
setAnyoneProjectPermission(view, UserRole.USER);
userSessionRule.login("john").addProjectUuidPermissions(UserRole.USER, view.uuid());

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, view.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, view.uuid())
.execute()
.assertJson(this.getClass(), "search_by_view_uuid.json");
}
@@ -507,8 +508,8 @@ public class SearchActionComponentsMediumTest {
// User has wrong permission on the view, no issue will be returned
userSessionRule.login("john").addProjectUuidPermissions(UserRole.CODEVIEWER, view.uuid());

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, view.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, view.uuid())
.execute()
.assertJson(this.getClass(), "no_issue.json");
}
@@ -528,8 +529,8 @@ public class SearchActionComponentsMediumTest {
setAnyoneProjectPermission(view, UserRole.USER);
userSessionRule.login("john").addComponentUuidPermission(UserRole.USER, view.uuid(), subView.uuid());

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, subView.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, subView.uuid())
.execute()
.assertJson(this.getClass(), "search_by_view_uuid.json");
}
@@ -550,8 +551,8 @@ public class SearchActionComponentsMediumTest {
// User has wrong permission on the view, no issue will be returned
userSessionRule.login("john").addComponentUuidPermission(UserRole.CODEVIEWER, view.uuid(), subView.uuid());

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, subView.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, subView.uuid())
.execute()
.assertJson(this.getClass(), "no_issue.json");
}
@@ -569,14 +570,14 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.AUTHORS, "leia")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_AUTHORS, "leia")
.setParam(WebService.Param.FACETS, "authors")
.execute()
.assertJson(this.getClass(), "search_by_authors.json");

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.AUTHORS, "unknown")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_AUTHORS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");

@@ -598,8 +599,8 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, developer.uuid())
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, developer.uuid())
.execute()
.assertJson(this.getClass(), "search_by_developer.json");
}
@@ -630,8 +631,8 @@ public class SearchActionComponentsMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SearchAction.SEARCH_ACTION)
.setParam(IssuesWsParameters.COMPONENT_UUIDS, technicalProject.uuid())
Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(IssuesWsParameters.PARAM_COMPONENT_UUIDS, technicalProject.uuid())
.execute();
result
.assertJson(this.getClass(), "search_by_developer.json");

+ 33
- 33
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java View File

@@ -58,16 +58,16 @@ import org.sonar.server.ws.WsTester;

import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.server.issue.ws.SearchAction.SEARCH_ACTION;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ADDITIONAL_FIELDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SEARCH;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CONTROLLER_ISSUES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_AFTER;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_FACET_MODE_DEBT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE_EFFORT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.HIDE_COMMENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PAGE_INDEX;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PAGE_SIZE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ADDITIONAL_FIELDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AFTER;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_HIDE_COMMENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PAGE_INDEX;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PAGE_SIZE;

public class SearchActionMediumTest {

@@ -112,7 +112,7 @@ public class SearchActionMediumTest {

@Test
public void empty_search() throws Exception {
WsTester.TestRequest request = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION);
WsTester.TestRequest request = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH);
WsTester.Result result = request.execute();

assertThat(result).isNotNull();
@@ -143,7 +143,7 @@ public class SearchActionMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION).execute();
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH).execute();
result.assertJson(this.getClass(), "response_contains_all_fields_except_additional_fields.json");
}

@@ -177,7 +177,7 @@ public class SearchActionMediumTest {
tester.get(IssueIndexer.class).indexAll();

userSessionRule.login("john");
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam("additionalFields", "comments,users")
.execute();
result.assertJson(this.getClass(), "issue_with_comments.json");
@@ -213,7 +213,7 @@ public class SearchActionMediumTest {
tester.get(IssueIndexer.class).indexAll();

userSessionRule.login("john");
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION).setParam(HIDE_COMMENTS, "true").execute();
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH).setParam(PARAM_HIDE_COMMENTS, "true").execute();
result.assertJson(this.getClass(), "issue_with_comment_hidden.json");
assertThat(result.outputAsString()).doesNotContain("fabrice");
}
@@ -235,7 +235,7 @@ public class SearchActionMediumTest {
tester.get(IssueIndexer.class).indexAll();

userSessionRule.login("john");
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam("additionalFields", "_all").execute();
result.assertJson(this.getClass(), "load_additional_fields.json");
}
@@ -260,7 +260,7 @@ public class SearchActionMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.execute();
result.assertJson(this.getClass(), "issue_on_removed_file.json");
}
@@ -275,7 +275,7 @@ public class SearchActionMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION).execute();
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH).execute();
assertThat(result.outputAsString()).contains("\"componentId\":" + file.getId() + ",");
}

@@ -292,7 +292,7 @@ public class SearchActionMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION).setParam(COMPONENTS, file.getKey()).execute();
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH).setParam(PARAM_COMPONENTS, file.getKey()).execute();
result.assertJson(this.getClass(), "apply_paging_with_one_component.json");
}

@@ -307,7 +307,7 @@ public class SearchActionMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION).setParam(ADDITIONAL_FIELDS, "_all").execute();
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH).setParam(PARAM_ADDITIONAL_FIELDS, "_all").execute();
result.assertJson(this.getClass(), "components_contains_sub_projects.json");
}

@@ -328,7 +328,7 @@ public class SearchActionMediumTest {
tester.get(IssueIndexer.class).indexAll();

userSessionRule.login("john");
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam("resolved", "false")
.setParam(WebService.Param.FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,languages,actionPlans,types")
.execute();
@@ -352,7 +352,7 @@ public class SearchActionMediumTest {
tester.get(IssueIndexer.class).indexAll();

userSessionRule.login("john");
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam("resolved", "false")
.setParam(WebService.Param.FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,languages,actionPlans")
.setParam("facetMode", FACET_MODE_EFFORT)
@@ -377,7 +377,7 @@ public class SearchActionMediumTest {
tester.get(IssueIndexer.class).indexAll();

userSessionRule.login("john");
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam("resolved", "false")
.setParam("severities", "MAJOR,MINOR")
.setParam("languages", "xoo,polop,palap")
@@ -392,7 +392,7 @@ public class SearchActionMediumTest {
userSessionRule.login("foo[");

// should not fail
wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(WebService.Param.FACETS, "assigned_to_me")
.execute()
.assertJson(this.getClass(), "assignedToMe_facet_must_escape_login_of_authenticated_user.json");
@@ -435,7 +435,7 @@ public class SearchActionMediumTest {
tester.get(IssueIndexer.class).indexAll();

userSessionRule.login("john");
wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam("resolved", "false")
.setParam("assignees", "__me__")
.setParam(WebService.Param.FACETS, "assignees,assigned_to_me")
@@ -466,7 +466,7 @@ public class SearchActionMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam("resolved", "false")
.setParam("assignees", "__me__")
.execute()
@@ -509,7 +509,7 @@ public class SearchActionMediumTest {
tester.get(IssueIndexer.class).indexAll();

userSessionRule.login("john-bob.polop");
wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam("resolved", "false")
.setParam("assignees", "alice")
.setParam(WebService.Param.FACETS, "assignees,assigned_to_me")
@@ -535,7 +535,7 @@ public class SearchActionMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam("sort", IssueQuery.SORT_BY_UPDATE_DATE)
.setParam("asc", "false")
.execute();
@@ -555,7 +555,7 @@ public class SearchActionMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

WsTester.TestRequest request = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION);
WsTester.TestRequest request = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH);
request.setParam(WebService.Param.PAGE, "2");
request.setParam(WebService.Param.PAGE_SIZE, "9");

@@ -576,7 +576,7 @@ public class SearchActionMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

WsTester.TestRequest request = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION);
WsTester.TestRequest request = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH);
request.setParam(WebService.Param.PAGE, "1");
request.setParam(WebService.Param.PAGE_SIZE, "-1");

@@ -597,9 +597,9 @@ public class SearchActionMediumTest {
session.commit();
tester.get(IssueIndexer.class).indexAll();

WsTester.TestRequest request = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION);
request.setParam(PAGE_INDEX, "2");
request.setParam(PAGE_SIZE, "9");
WsTester.TestRequest request = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH);
request.setParam(PARAM_PAGE_INDEX, "2");
request.setParam(PARAM_PAGE_SIZE, "9");

WsTester.Result result = request.execute();
result.assertJson(this.getClass(), "deprecated_paging.json");
@@ -607,7 +607,7 @@ public class SearchActionMediumTest {

@Test
public void default_page_size_is_100() throws Exception {
WsTester.TestRequest request = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION);
WsTester.TestRequest request = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH);

WsTester.Result result = request.execute();
result.assertJson(this.getClass(), "default_page_size_is_100.json");
@@ -630,7 +630,7 @@ public class SearchActionMediumTest {
tester.get(IssueIndexer.class).indexAll();

userSessionRule.login("john");
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
WsTester.Result result = wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam("resolved", "false")
.setParam(WebService.Param.FACETS, "severities")
.setParam("facetMode", DEPRECATED_FACET_MODE_DEBT)
@@ -643,8 +643,8 @@ public class SearchActionMediumTest {
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("Date 'wrong-date-input' cannot be parsed as either a date or date+time");

wsTester.newGetRequest(CONTROLLER_ISSUES, SEARCH_ACTION)
.setParam(CREATED_AFTER, "wrong-date-input")
wsTester.newGetRequest(CONTROLLER_ISSUES, ACTION_SEARCH)
.setParam(PARAM_CREATED_AFTER, "wrong-date-input")
.execute();
}


+ 10
- 1
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SetTagsActionTest.java View File

@@ -59,7 +59,7 @@ public class SetTagsActionTest {
assertThat(action.handler()).isEqualTo(sut);
assertThat(action.params()).hasSize(2);

Param query = action.param("key");
Param query = action.param("issue");
assertThat(query.isRequired()).isTrue();
assertThat(query.description()).isNotEmpty();
assertThat(query.exampleValue()).isNotEmpty();
@@ -72,9 +72,18 @@ public class SetTagsActionTest {

@Test
public void should_set_tags() throws Exception {
when(service.setTags("polop", ImmutableList.of("palap"))).thenReturn(ImmutableSet.of("palap"));
tester.newPostRequest("api/issues", "set_tags").setParam("issue", "polop").setParam("tags", "palap").execute()
.assertJson("{\"tags\":[\"palap\"]}");
verify(service).setTags("polop", ImmutableList.of("palap"));
}

@Test
public void should_set_tags_with_deprecated_key() throws Exception {
when(service.setTags("polop", ImmutableList.of("palap"))).thenReturn(ImmutableSet.of("palap"));
tester.newPostRequest("api/issues", "set_tags").setParam("key", "polop").setParam("tags", "palap").execute()
.assertJson("{\"tags\":[\"palap\"]}");
verify(service).setTags("polop", ImmutableList.of("palap"));
}

}

+ 42
- 0
sonar-ws/src/main/java/org/sonarqube/ws/client/issue/AddCommentRequest.java View File

@@ -0,0 +1,42 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program 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.
*
* This program 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.sonarqube.ws.client.issue;

import static java.util.Objects.requireNonNull;

public class AddCommentRequest {

private final String issue;
private final String comment;

public AddCommentRequest(String issue, String comment) {
this.issue = requireNonNull(issue, "Issue key cannot be null");
this.comment = requireNonNull(comment, "Comment cannot be null");
}

public String getIssue() {
return issue;
}

public String getComment() {
return comment;
}
}

+ 46
- 0
sonar-ws/src/main/java/org/sonarqube/ws/client/issue/AssignRequest.java View File

@@ -0,0 +1,46 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program 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.
*
* This program 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.sonarqube.ws.client.issue;

import javax.annotation.CheckForNull;
import javax.annotation.Nullable;

import static java.util.Objects.requireNonNull;

public class AssignRequest {

private final String issue;
private final String assignee;

public AssignRequest(String issue, @Nullable String assignee) {
this.issue = requireNonNull(issue, "Issue key cannot be null");
this.assignee = assignee;
}

public String getIssue() {
return issue;
}

@CheckForNull
public String getAssignee() {
return assignee;
}
}

+ 42
- 0
sonar-ws/src/main/java/org/sonarqube/ws/client/issue/DoTransitionRequest.java View File

@@ -0,0 +1,42 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program 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.
*
* This program 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.sonarqube.ws.client.issue;

import static java.util.Objects.requireNonNull;

public class DoTransitionRequest {

private final String issue;
private final String transition;

public DoTransitionRequest(String issue, String transition) {
this.issue = requireNonNull(issue, "Issue key cannot be null");
this.transition = requireNonNull(transition, "Transition cannot be null");
}

public String getIssue() {
return issue;
}

public String getTransition() {
return transition;
}
}

+ 119
- 77
sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesService.java View File

@@ -27,44 +27,57 @@ import org.sonarqube.ws.client.GetRequest;
import org.sonarqube.ws.client.PostRequest;
import org.sonarqube.ws.client.WsConnector;

import static org.sonar.api.server.ws.WebService.Param.FACETS;
import static org.sonar.api.server.ws.WebService.Param.PAGE;
import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
import static org.sonar.api.server.ws.WebService.Param.SORT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_ADD_COMMENT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_ASSIGN;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_CHANGELOG;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ADDITIONAL_FIELDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ASC;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ASSIGNED;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ASSIGNEES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.AUTHORS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENT_ROOTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENT_ROOT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.COMPONENT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_DO_TRANSITION;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SEARCH;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SET_SEVERITY;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ACTION_SET_TYPE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CONTROLLER_ISSUES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_AFTER;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_AT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_BEFORE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.CREATED_IN_LAST;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.DEPRECATED_PARAM_ACTION_PLANS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FACET_MODE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.FILE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ISSUES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.LANGUAGES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.MODULE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.ON_COMPONENT_ONLY;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ADDITIONAL_FIELDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASC;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNED;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNEE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ASSIGNEES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_AUTHORS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_ROOTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_ROOT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_COMPONENT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AFTER;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_AT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_BEFORE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_CREATED_IN_LAST;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_DIRECTORIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_FILE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_LANGUAGES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_MODULE_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ON_COMPONENT_ONLY;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PROJECT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RESOLUTIONS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RESOLVED;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RULES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SEVERITIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SEVERITY;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SINCE_LEAK_PERIOD;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TAGS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TEXT;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PROJECTS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PROJECT_KEYS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PROJECT_UUIDS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.RESOLUTIONS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.RESOLVED;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.RULES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.SEVERITIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.SINCE_LEAK_PERIOD;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.TAGS;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.TYPES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TRANSITION;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TYPE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TYPES;

public class IssuesService extends BaseService {

@@ -72,47 +85,18 @@ public class IssuesService extends BaseService {
super(wsConnector, CONTROLLER_ISSUES);
}

public SearchWsResponse search(SearchWsRequest request) {
return call(
new GetRequest(path("search"))
.setParam(DEPRECATED_ACTION_PLANS, inlineMultipleParamValue(request.getActionPlans()))
.setParam(ADDITIONAL_FIELDS, inlineMultipleParamValue(request.getAdditionalFields()))
.setParam(ASC, request.getAsc())
.setParam(ASSIGNED, request.getAssigned())
.setParam(ASSIGNEES, inlineMultipleParamValue(request.getAssignees()))
.setParam(AUTHORS, inlineMultipleParamValue(request.getAuthors()))
.setParam(COMPONENT_KEYS, inlineMultipleParamValue(request.getComponentKeys()))
.setParam(COMPONENT_ROOT_UUIDS, inlineMultipleParamValue(request.getComponentRootUuids()))
.setParam(COMPONENT_ROOTS, inlineMultipleParamValue(request.getComponentRoots()))
.setParam(COMPONENT_UUIDS, inlineMultipleParamValue(request.getComponentUuids()))
.setParam(COMPONENTS, inlineMultipleParamValue(request.getComponents()))
.setParam(CREATED_AFTER, request.getCreatedAfter())
.setParam(CREATED_AT, request.getCreatedAt())
.setParam(CREATED_BEFORE, request.getCreatedBefore())
.setParam(CREATED_IN_LAST, request.getCreatedInLast())
.setParam(DIRECTORIES, inlineMultipleParamValue(request.getDirectories()))
.setParam(FACET_MODE, request.getFacetMode())
.setParam("facets", inlineMultipleParamValue(request.getFacets()))
.setParam(FILE_UUIDS, inlineMultipleParamValue(request.getFileUuids()))
.setParam(ISSUES, inlineMultipleParamValue(request.getIssues()))
.setParam(LANGUAGES, inlineMultipleParamValue(request.getLanguages()))
.setParam(MODULE_UUIDS, inlineMultipleParamValue(request.getModuleUuids()))
.setParam(ON_COMPONENT_ONLY, request.getOnComponentOnly())
.setParam("p", request.getPage())
.setParam("ps", request.getPageSize())
.setParam(PROJECT_KEYS, inlineMultipleParamValue(request.getProjectKeys()))
.setParam(PROJECT_UUIDS, inlineMultipleParamValue(request.getProjectUuids()))
.setParam(PROJECTS, inlineMultipleParamValue(request.getProjects()))
.setParam(RESOLUTIONS, inlineMultipleParamValue(request.getResolutions()))
.setParam(RESOLVED, request.getResolved())
.setParam(RULES, inlineMultipleParamValue(request.getRules()))
.setParam("s", request.getSort())
.setParam(SEVERITIES, inlineMultipleParamValue(request.getSeverities()))
.setParam(SINCE_LEAK_PERIOD, request.getSinceLeakPeriod())
.setParam(STATUSES, inlineMultipleParamValue(request.getStatuses()))
.setParam(TAGS, inlineMultipleParamValue(request.getTags()))
.setParam(TYPES, inlineMultipleParamValue(request.getTypes())),
SearchWsResponse.parser());
public Issues.Operation addComment(AddCommentRequest request) {
return call(new PostRequest(path(ACTION_ADD_COMMENT))
.setParam(PARAM_ISSUE, request.getIssue())
.setParam(PARAM_TEXT, request.getComment()),
Issues.Operation.parser());
}

public Issues.Operation assign(AssignRequest request) {
return call(new PostRequest(path(ACTION_ASSIGN))
.setParam(PARAM_ISSUE, request.getIssue())
.setParam(PARAM_ASSIGNEE, request.getAssignee()),
Issues.Operation.parser());
}

public ChangelogWsResponse changelog(String issueKey) {
@@ -121,10 +105,68 @@ public class IssuesService extends BaseService {
ChangelogWsResponse.parser());
}

public Issues.Operation addComment(String issueKey, String commentText) {
return call(new PostRequest(path(ACTION_ADD_COMMENT))
.setParam(PARAM_ISSUE, issueKey)
.setParam(PARAM_TEXT, commentText),
public Issues.Operation doTransition(DoTransitionRequest request) {
return call(new PostRequest(path(ACTION_DO_TRANSITION))
.setParam(PARAM_ISSUE, request.getIssue())
.setParam(PARAM_TRANSITION, request.getTransition()),
Issues.Operation.parser());
}

public SearchWsResponse search(SearchWsRequest request) {
return call(
new GetRequest(path(ACTION_SEARCH))
.setParam(DEPRECATED_PARAM_ACTION_PLANS, inlineMultipleParamValue(request.getActionPlans()))
.setParam(PARAM_ADDITIONAL_FIELDS, inlineMultipleParamValue(request.getAdditionalFields()))
.setParam(PARAM_ASC, request.getAsc())
.setParam(PARAM_ASSIGNED, request.getAssigned())
.setParam(PARAM_ASSIGNEES, inlineMultipleParamValue(request.getAssignees()))
.setParam(PARAM_AUTHORS, inlineMultipleParamValue(request.getAuthors()))
.setParam(PARAM_COMPONENT_KEYS, inlineMultipleParamValue(request.getComponentKeys()))
.setParam(PARAM_COMPONENT_ROOT_UUIDS, inlineMultipleParamValue(request.getComponentRootUuids()))
.setParam(PARAM_COMPONENT_ROOTS, inlineMultipleParamValue(request.getComponentRoots()))
.setParam(PARAM_COMPONENT_UUIDS, inlineMultipleParamValue(request.getComponentUuids()))
.setParam(PARAM_COMPONENTS, inlineMultipleParamValue(request.getComponents()))
.setParam(PARAM_CREATED_AFTER, request.getCreatedAfter())
.setParam(PARAM_CREATED_AT, request.getCreatedAt())
.setParam(PARAM_CREATED_BEFORE, request.getCreatedBefore())
.setParam(PARAM_CREATED_IN_LAST, request.getCreatedInLast())
.setParam(PARAM_DIRECTORIES, inlineMultipleParamValue(request.getDirectories()))
.setParam(FACET_MODE, request.getFacetMode())
.setParam(FACETS, inlineMultipleParamValue(request.getFacets()))
.setParam(PARAM_FILE_UUIDS, inlineMultipleParamValue(request.getFileUuids()))
.setParam(PARAM_ISSUES, inlineMultipleParamValue(request.getIssues()))
.setParam(PARAM_LANGUAGES, inlineMultipleParamValue(request.getLanguages()))
.setParam(PARAM_MODULE_UUIDS, inlineMultipleParamValue(request.getModuleUuids()))
.setParam(PARAM_ON_COMPONENT_ONLY, request.getOnComponentOnly())
.setParam(PAGE, request.getPage())
.setParam(PAGE_SIZE, request.getPageSize())
.setParam(PARAM_PROJECT_KEYS, inlineMultipleParamValue(request.getProjectKeys()))
.setParam(PARAM_PROJECT_UUIDS, inlineMultipleParamValue(request.getProjectUuids()))
.setParam(PARAM_PROJECTS, inlineMultipleParamValue(request.getProjects()))
.setParam(PARAM_RESOLUTIONS, inlineMultipleParamValue(request.getResolutions()))
.setParam(PARAM_RESOLVED, request.getResolved())
.setParam(PARAM_RULES, inlineMultipleParamValue(request.getRules()))
.setParam(SORT, request.getSort())
.setParam(PARAM_SEVERITIES, inlineMultipleParamValue(request.getSeverities()))
.setParam(PARAM_SINCE_LEAK_PERIOD, request.getSinceLeakPeriod())
.setParam(PARAM_STATUSES, inlineMultipleParamValue(request.getStatuses()))
.setParam(PARAM_TAGS, inlineMultipleParamValue(request.getTags()))
.setParam(PARAM_TYPES, inlineMultipleParamValue(request.getTypes())),
SearchWsResponse.parser());
}

public Issues.Operation setSeverity(SetSeverityRequest request) {
return call(new PostRequest(path(ACTION_SET_SEVERITY))
.setParam(PARAM_ISSUE, request.getIssue())
.setParam(PARAM_SEVERITY, request.getSeverity()),
Issues.Operation.parser());
}

public Issues.Operation setType(SetTypeRequest request) {
return call(new PostRequest(path(ACTION_SET_TYPE))
.setParam(PARAM_ISSUE, request.getIssue())
.setParam(PARAM_TYPE, request.getType()),
Issues.Operation.parser());
}

}

+ 58
- 55
sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesWsParameters.java View File

@@ -19,9 +19,7 @@
*/
package org.sonarqube.ws.client.issue;

import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.util.List;

/**
@@ -31,66 +29,78 @@ public class IssuesWsParameters {

public static final String CONTROLLER_ISSUES = "api/issues";

public static final String ACTION_SEARCH = "search";
public static final String ACTION_CHANGELOG = "changelog";
public static final String ACTION_ADD_COMMENT = "add_comment";
public static final String ACTION_ASSIGN = "assign";
public static final String ACTION_AUTHORS = "authors";
public static final String ACTION_DO_TRANSITION = "do_transition";
public static final String ACTION_SET_SEVERITY = "set_severity";
public static final String ACTION_COMPONENT_TAGS = "component_tags";
public static final String ACTION_SET_TAGS = "set_tags";
public static final String ACTION_SET_TYPE = "set_type";

public static final String PARAM_ISSUE = "issue";
public static final String PARAM_TEXT = "text";

public static final String ISSUES = "issues";
public static final String SEVERITIES = "severities";
public static final String STATUSES = "statuses";
public static final String RESOLUTIONS = "resolutions";
public static final String RESOLVED = "resolved";
public static final String COMPONENTS = "components";
public static final String COMPONENT_KEYS = "componentKeys";
public static final String COMPONENT_UUIDS = "componentUuids";
public static final String COMPONENT_ROOTS = "componentRoots";
public static final String COMPONENT_ROOT_UUIDS = "componentRootUuids";
public static final String MODULE_UUIDS = "moduleUuids";
public static final String PROJECTS = "projects";
public static final String PROJECT_KEYS = "projectKeys";
public static final String PROJECT_UUIDS = "projectUuids";
public static final String DIRECTORIES = "directories";
public static final String FILE_UUIDS = "fileUuids";
public static final String ON_COMPONENT_ONLY = "onComponentOnly";
public static final String RULES = "rules";
public static final String PARAM_ASSIGNEE = "assignee";
public static final String PARAM_TRANSITION = "transition";
public static final String PARAM_SEVERITY = "severity";
public static final String PARAM_COMPONENT_UUID = "componentUuid";
public static final String PARAM_TYPE = "type";
public static final String PARAM_ISSUES = "issues";
public static final String PARAM_SEVERITIES = "severities";
public static final String PARAM_STATUSES = "statuses";
public static final String PARAM_RESOLUTIONS = "resolutions";
public static final String PARAM_RESOLVED = "resolved";
public static final String PARAM_COMPONENTS = "components";
public static final String PARAM_COMPONENT_KEYS = "componentKeys";
public static final String PARAM_COMPONENT_UUIDS = "componentUuids";
public static final String PARAM_COMPONENT_ROOTS = "componentRoots";
public static final String PARAM_COMPONENT_ROOT_UUIDS = "componentRootUuids";
public static final String PARAM_MODULE_UUIDS = "moduleUuids";
public static final String PARAM_PROJECTS = "projects";
public static final String PARAM_PROJECT_KEYS = "projectKeys";
public static final String PARAM_PROJECT_UUIDS = "projectUuids";
public static final String PARAM_DIRECTORIES = "directories";
public static final String PARAM_FILE_UUIDS = "fileUuids";
public static final String PARAM_ON_COMPONENT_ONLY = "onComponentOnly";
public static final String PARAM_RULES = "rules";

/**
* @deprecated since 5.5, action plan feature has been removed
*/
@Deprecated
public static final String DEPRECATED_ACTION_PLANS = "actionPlans";
public static final String DEPRECATED_PARAM_ACTION_PLANS = "actionPlans";

/**
* @deprecated since 5.5, manual issue feature has been dropped.
*/
@Deprecated
public static final String REPORTERS = "reporters";
public static final String ASSIGNEES = "assignees";
public static final String AUTHORS = "authors";
public static final String LANGUAGES = "languages";
public static final String TAGS = "tags";
public static final String TYPES = "types";
public static final String ASSIGNED = "assigned";
public static final String PARAM_REPORTERS = "reporters";
public static final String PARAM_ASSIGNEES = "assignees";
public static final String PARAM_AUTHORS = "authors";
public static final String PARAM_LANGUAGES = "languages";
public static final String PARAM_TAGS = "tags";
public static final String PARAM_TYPES = "types";
public static final String PARAM_ASSIGNED = "assigned";

/**
* @deprecated since 5.5, action plan feature has been removed
*/
@Deprecated
public static final String PLANNED = "planned";
public static final String HIDE_RULES = "hideRules";
public static final String HIDE_COMMENTS = "hideComments";
public static final String CREATED_AFTER = "createdAfter";
public static final String CREATED_AT = "createdAt";
public static final String CREATED_BEFORE = "createdBefore";
public static final String CREATED_IN_LAST = "createdInLast";
public static final String SINCE_LEAK_PERIOD = "sinceLeakPeriod";
public static final String PAGE_SIZE = "pageSize";
public static final String PAGE_INDEX = "pageIndex";
public static final String SORT = "sort";
public static final String ASC = "asc";
public static final String ADDITIONAL_FIELDS = "additionalFields";
public static final String PARAM_PLANNED = "planned";
public static final String PARAM_HIDE_RULES = "hideRules";
public static final String PARAM_HIDE_COMMENTS = "hideComments";
public static final String PARAM_CREATED_AFTER = "createdAfter";
public static final String PARAM_CREATED_AT = "createdAt";
public static final String PARAM_CREATED_BEFORE = "createdBefore";
public static final String PARAM_CREATED_IN_LAST = "createdInLast";
public static final String PARAM_SINCE_LEAK_PERIOD = "sinceLeakPeriod";
public static final String PARAM_PAGE_SIZE = "pageSize";
public static final String PARAM_PAGE_INDEX = "pageIndex";
public static final String PARAM_SORT = "sort";
public static final String PARAM_ASC = "asc";
public static final String PARAM_ADDITIONAL_FIELDS = "additionalFields";

public static final String FACET_MODE = "facetMode";
public static final String FACET_MODE_COUNT = "count";
@@ -104,19 +114,12 @@ public class IssuesWsParameters {

public static final String FACET_ASSIGNED_TO_ME = "assigned_to_me";

public static final List<String> ALL = ImmutableList.of(ISSUES, SEVERITIES, STATUSES, RESOLUTIONS, RESOLVED,
COMPONENTS, COMPONENT_ROOTS, RULES, DEPRECATED_ACTION_PLANS, REPORTERS, TAGS, TYPES,
ASSIGNEES, LANGUAGES, ASSIGNED, PLANNED, HIDE_RULES, CREATED_AT, CREATED_AFTER, CREATED_BEFORE, CREATED_IN_LAST,
COMPONENT_UUIDS, COMPONENT_ROOT_UUIDS, FACET_MODE,
PROJECTS, PROJECT_UUIDS, PROJECT_KEYS, COMPONENT_KEYS, MODULE_UUIDS, DIRECTORIES, FILE_UUIDS, AUTHORS,
HIDE_COMMENTS, PAGE_SIZE, PAGE_INDEX, SORT, ASC);

public static final List<String> ALL_WITHOUT_PAGINATION = ImmutableList.copyOf(Iterables.filter(ALL, new Predicate<String>() {
@Override
public boolean apply(String input) {
return !PAGE_INDEX.equals(input) && !PAGE_SIZE.equals(input);
}
}));
public static final List<String> ALL = ImmutableList.of(PARAM_ISSUES, PARAM_SEVERITIES, PARAM_STATUSES, PARAM_RESOLUTIONS, PARAM_RESOLVED,
PARAM_COMPONENTS, PARAM_COMPONENT_ROOTS, PARAM_RULES, DEPRECATED_PARAM_ACTION_PLANS, PARAM_REPORTERS, PARAM_TAGS, PARAM_TYPES,
PARAM_ASSIGNEES, PARAM_LANGUAGES, PARAM_ASSIGNED, PARAM_PLANNED, PARAM_HIDE_RULES, PARAM_CREATED_AT, PARAM_CREATED_AFTER, PARAM_CREATED_BEFORE, PARAM_CREATED_IN_LAST,
PARAM_COMPONENT_UUIDS, PARAM_COMPONENT_ROOT_UUIDS, FACET_MODE,
PARAM_PROJECTS, PARAM_PROJECT_UUIDS, PARAM_PROJECT_KEYS, PARAM_COMPONENT_KEYS, PARAM_MODULE_UUIDS, PARAM_DIRECTORIES, PARAM_FILE_UUIDS, PARAM_AUTHORS,
PARAM_HIDE_COMMENTS, PARAM_PAGE_SIZE, PARAM_PAGE_INDEX, PARAM_SORT, PARAM_ASC);

private IssuesWsParameters() {
// Utility class

+ 42
- 0
sonar-ws/src/main/java/org/sonarqube/ws/client/issue/SetSeverityRequest.java View File

@@ -0,0 +1,42 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program 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.
*
* This program 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.sonarqube.ws.client.issue;

import static java.util.Objects.requireNonNull;

public class SetSeverityRequest {

private final String issue;
private final String severity;

public SetSeverityRequest(String issue, String severity) {
this.issue = requireNonNull(issue, "Issue key cannot be null");
this.severity = requireNonNull(severity, "Severity cannot be null");
}

public String getIssue() {
return issue;
}

public String getSeverity() {
return severity;
}
}

+ 42
- 0
sonar-ws/src/main/java/org/sonarqube/ws/client/issue/SetTypeRequest.java View File

@@ -0,0 +1,42 @@
/*
* SonarQube
* Copyright (C) 2009-2016 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* This program 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.
*
* This program 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.sonarqube.ws.client.issue;

import static java.util.Objects.requireNonNull;

public class SetTypeRequest {

private final String issue;
private final String type;

public SetTypeRequest(String issue, String type) {
this.issue = requireNonNull(issue, "Issue key cannot be null");
this.type = requireNonNull(type, "Type cannot be null");
}

public String getIssue() {
return issue;
}

public String getType() {
return type;
}
}

+ 52
- 8
sonar-ws/src/test/java/org/sonarqube/ws/client/issue/IssuesServiceTest.java View File

@@ -30,8 +30,6 @@ import org.sonarqube.ws.client.WsConnector;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TEXT;

public class IssuesServiceTest {

@@ -40,28 +38,74 @@ public class IssuesServiceTest {

private IssuesService underTest = serviceTester.getInstanceUnderTest();

@Test
public void add_comment() {
underTest.addComment(new AddCommentRequest("ABCD", "Please help me to fix this issue"));
PostRequest request = serviceTester.getPostRequest();

assertThat(serviceTester.getPostParser()).isSameAs(Issues.Operation.parser());
serviceTester.assertThat(request)
.hasParam("issue", "ABCD")
.hasParam("text", "Please help me to fix this issue")
.andNoOtherParam();
}

@Test
public void assign() {
underTest.assign(new AssignRequest("ABCD", "teryk"));
PostRequest request = serviceTester.getPostRequest();

assertThat(serviceTester.getPostParser()).isSameAs(Issues.Operation.parser());
serviceTester.assertThat(request)
.hasParam("issue", "ABCD")
.hasParam("assignee", "teryk")
.andNoOtherParam();
}

@Test
public void changelog() {
underTest.changelog("ABCD");

GetRequest getRequest = serviceTester.getGetRequest();

assertThat(serviceTester.getGetParser()).isSameAs(Issues.ChangelogWsResponse.parser());
serviceTester.assertThat(getRequest)
.hasParam(PARAM_ISSUE, "ABCD")
.hasParam("issue", "ABCD")
.andNoOtherParam();
}

@Test
public void add_comment() {
underTest.addComment("ABCD", "Please help me to fix this issue");
public void do_transition() {
underTest.doTransition(new DoTransitionRequest("ABCD", "confirm"));
PostRequest request = serviceTester.getPostRequest();

assertThat(serviceTester.getPostParser()).isSameAs(Issues.Operation.parser());
serviceTester.assertThat(request)
.hasParam("issue", "ABCD")
.hasParam("transition", "confirm")
.andNoOtherParam();
}

@Test
public void set_severity() {
underTest.setSeverity(new SetSeverityRequest("ABCD", "confirm"));
PostRequest request = serviceTester.getPostRequest();

assertThat(serviceTester.getPostParser()).isSameAs(Issues.Operation.parser());
serviceTester.assertThat(request)
.hasParam("issue", "ABCD")
.hasParam("severity", "confirm")
.andNoOtherParam();
}

@Test
public void set_type() {
underTest.setType(new SetTypeRequest("ABCD", "bugs"));
PostRequest request = serviceTester.getPostRequest();

assertThat(serviceTester.getPostParser()).isSameAs(Issues.Operation.parser());
serviceTester.assertThat(request)
.hasParam(PARAM_ISSUE, "ABCD")
.hasParam(PARAM_TEXT, "Please help me to fix this issue")
.hasParam("issue", "ABCD")
.hasParam("type", "bugs")
.andNoOtherParam();
}


Loading…
Cancel
Save