+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.component.ws;
-
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.db.component.ComponentDto;
-
-public class ComponentJsonWriter {
-
- public void write(JsonWriter json, ComponentDto component, ComponentDto project) {
- json.beginObject()
- .prop("uuid", component.uuid())
- .prop("key", component.key())
- .prop("id", component.getId())
- .prop("qualifier", component.qualifier())
- .prop("name", component.name())
- .prop("longName", component.longName())
- .prop("enabled", component.isEnabled())
- .prop("path", component.path())
- // On a root project, parentProjectId is null but projectId is equal to itself, which make no sense.
- .prop("projectId", (component.projectUuid() != null && component.parentProjectId() != null) ? project.getId() : null)
- // TODO replace with parentProjectId when sonar-ws-client is not used anymore by tests...
- .prop("subProjectId", component.parentProjectId())
- .endObject();
- }
-}
package org.sonar.server.issue;
import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
-import java.io.StringWriter;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
import org.sonar.api.issue.ActionPlan;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.IssueComment;
-import org.sonar.api.issue.action.Action;
-import org.sonar.api.rule.RuleKey;
import org.sonar.api.server.ServerSide;
-import org.sonar.api.user.User;
import org.sonar.api.utils.SonarException;
-import org.sonar.api.utils.text.JsonWriter;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.ActionPlanStats;
import org.sonar.core.issue.DefaultActionPlan;
-import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.DefaultIssueComment;
import org.sonar.core.issue.FieldDiffs;
import org.sonar.core.issue.workflow.Transition;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.MyBatis;
-import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ResourceDao;
import org.sonar.db.component.ResourceDto;
import org.sonar.db.component.ResourceQuery;
import org.sonar.db.issue.IssueFilterDto;
-import org.sonar.server.component.ws.ComponentJsonWriter;
import org.sonar.server.es.SearchOptions;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.issue.actionplan.ActionPlanService;
import org.sonar.server.issue.filter.IssueFilterParameters;
import org.sonar.server.issue.filter.IssueFilterService;
-import org.sonar.server.issue.ws.IssueComponentHelper;
-import org.sonar.server.issue.ws.IssueJsonWriter;
import org.sonar.server.search.QueryContext;
import org.sonar.server.user.UserSession;
-import org.sonar.server.user.index.UserIndex;
-import org.sonar.server.user.ws.UserJsonWriter;
import org.sonar.server.util.RubyUtils;
import org.sonar.server.util.Validation;
-import static com.google.common.collect.Maps.newHashMap;
-
/**
* Used through ruby code <pre>Internal.issues</pre>
* <p/>
private static final String ACTION_PLANS_ERRORS_ACTION_PLAN_DOES_NOT_EXIST_MESSAGE = "action_plans.errors.action_plan_does_not_exist";
- private static final List<String> ISSUE_FIELDS = ImmutableList.copyOf(IssueJsonWriter.SELECTABLE_FIELDS);
-
private final IssueService issueService;
private final IssueQueryService issueQueryService;
private final IssueCommentService commentService;
private final IssueChangelogService changelogService;
private final ActionPlanService actionPlanService;
private final ResourceDao resourceDao;
- private final ActionService actionService;
private final IssueFilterService issueFilterService;
private final IssueBulkChangeService issueBulkChangeService;
- private final IssueJsonWriter issueWriter;
- private final IssueComponentHelper issueComponentHelper;
- private final ComponentJsonWriter componentWriter;
- private final UserIndex userIndex;
- private final DbClient dbClient;
private final UserSession userSession;
- private final UserJsonWriter userWriter;
public InternalRubyIssueService(
IssueService issueService,
IssueQueryService issueQueryService,
IssueCommentService commentService,
IssueChangelogService changelogService, ActionPlanService actionPlanService,
- ResourceDao resourceDao, ActionService actionService,
+ ResourceDao resourceDao,
IssueFilterService issueFilterService, IssueBulkChangeService issueBulkChangeService,
- IssueJsonWriter issueWriter, IssueComponentHelper issueComponentHelper, ComponentJsonWriter componentWriter, UserIndex userIndex, DbClient dbClient,
- UserSession userSession, UserJsonWriter userWriter) {
+ UserSession userSession) {
this.issueService = issueService;
this.issueQueryService = issueQueryService;
this.commentService = commentService;
this.changelogService = changelogService;
this.actionPlanService = actionPlanService;
this.resourceDao = resourceDao;
- this.actionService = actionService;
this.issueFilterService = issueFilterService;
this.issueBulkChangeService = issueBulkChangeService;
- this.issueWriter = issueWriter;
- this.issueComponentHelper = issueComponentHelper;
- this.componentWriter = componentWriter;
- this.userIndex = userIndex;
- this.dbClient = dbClient;
this.userSession = userSession;
- this.userWriter = userWriter;
}
public List<Transition> listTransitions(String issueKey) {
return commentService.findComments(issueKeys);
}
- public Result<Issue> doTransition(String issueKey, String transitionKey) {
- Result<Issue> result = Result.of();
- try {
- result.set(issueService.doTransition(issueKey, transitionKey));
- } catch (Exception e) {
- result.addError(e.getMessage());
- }
- return result;
- }
-
- public Result<Issue> setSeverity(String issueKey, String severity) {
- Result<Issue> result = Result.of();
- try {
- result.set(issueService.setSeverity(issueKey, severity));
- } catch (Exception e) {
- result.addError(e.getMessage());
- }
- return result;
- }
-
- public Result<Issue> plan(String issueKey, @Nullable String actionPlanKey) {
- Result<Issue> result = Result.of();
- try {
- result.set(issueService.plan(issueKey, actionPlanKey));
- } catch (Exception e) {
- result.addError(e.getMessage());
- }
- return result;
- }
-
public Result<IssueComment> addComment(String issueKey, String text) {
Result<IssueComment> result = Result.of();
try {
return commentService.findComment(commentKey);
}
- /**
- * Create manual issue
- */
- public Result<DefaultIssue> create(Map<String, String> params) {
- Result<DefaultIssue> result = Result.of();
- try {
- // mandatory parameters
- String componentKey = params.get("component");
- if (StringUtils.isBlank(componentKey)) {
- result.addError("Component is not set");
- }
- RuleKey ruleKey = null;
- String rule = params.get("rule");
- if (StringUtils.isBlank(rule)) {
- result.addError(Result.Message.ofL10n("issue.manual.missing_rule"));
- } else {
- ruleKey = RuleKey.parse(rule);
- }
-
- if (result.ok()) {
- DefaultIssue issue = issueService.createManualIssue(componentKey, ruleKey, RubyUtils.toInteger(params.get("line")), params.get("message"), params.get("severity"),
- RubyUtils.toDouble(params.get("effortToFix")));
- result.set(issue);
- }
-
- } catch (Exception e) {
- result.addError(e.getMessage());
- }
- return result;
- }
-
public Collection<ActionPlan> findOpenActionPlans(String projectKey) {
return actionPlanService.findOpenByProjectKey(projectKey, userSession);
}
return userSession.hasProjectPermissionByUuid(UserRole.ISSUE_ADMIN, projectUuid);
}
- /**
- * Used by issue modification actions currently implemented in Rails
- *
- * @return the JSON representation of the modified issue, as a ready to use string
- */
- public String writeIssueJson(@Nullable Issue original) {
- if (original == null) {
- return "{}";
- }
-
- // Reloading from ES to avoid partial object, e.g for manual issues
- Issue issue = issueService.getByKey(original.key());
-
- StringWriter writer = new StringWriter();
- JsonWriter json = JsonWriter.of(writer);
- DbSession dbSession = dbClient.openSession(false);
- try {
- Map<String, User> usersByLogin = getIssueUsersByLogin(issue);
-
- Set<String> componentUuids = ImmutableSet.of(issue.componentUuid());
- Set<String> projectUuids = Sets.newHashSet();
- Set<ComponentDto> componentDtos = Sets.newHashSet();
- List<ComponentDto> projectDtos = Lists.newArrayList();
-
- Map<String, ComponentDto> componentsByUuid = Maps.newHashMap();
- Map<String, ComponentDto> projectsByComponentUuid = Maps.newHashMap();
-
- List<ComponentDto> fileDtos = dbClient.componentDao().selectByUuids(dbSession, componentUuids);
- List<ComponentDto> subProjectDtos = dbClient.componentDao().selectSubProjectsByComponentUuids(dbSession, componentUuids);
- componentDtos.addAll(fileDtos);
- componentDtos.addAll(subProjectDtos);
- for (ComponentDto component : componentDtos) {
- projectUuids.add(component.projectUuid());
- }
- projectDtos.addAll(dbClient.componentDao().selectByUuids(dbSession, projectUuids));
- componentDtos.addAll(projectDtos);
-
- for (ComponentDto componentDto : componentDtos) {
- componentsByUuid.put(componentDto.uuid(), componentDto);
- }
-
- projectsByComponentUuid = issueComponentHelper.prepareComponentsAndProjects(projectUuids, componentUuids, componentsByUuid, componentDtos, subProjectDtos, dbSession);
-
- Map<String, ActionPlan> actionPlans = newHashMap();
- String actionPlanKey = issue.actionPlanKey();
- if (actionPlanKey != null) {
- actionPlans.put(actionPlanKey, actionPlanService.findByKey(actionPlanKey, userSession));
- }
-
- json.beginObject().name("issue");
- issueWriter.write(json, issue,
- usersByLogin,
- componentsByUuid,
- projectsByComponentUuid,
- ImmutableMultimap.<String, DefaultIssueComment>of(),
- actionPlans,
- ISSUE_FIELDS);
-
- json.name("users").beginArray();
- String assignee = issue.assignee();
- if (assignee != null && usersByLogin.containsKey(assignee)) {
- userWriter.write(json, usersByLogin.get(assignee));
- }
- json.endArray();
-
- json.name("projects").beginArray();
- for (ComponentDto project : projectDtos) {
- componentWriter.write(json, project, project);
- }
- json.endArray();
-
- json.name("components").beginArray();
- for (ComponentDto component : componentDtos) {
- componentWriter.write(json, component, projectsByComponentUuid.get(component.uuid()));
- }
- json.endArray();
-
- json.endObject().close();
- } finally {
- MyBatis.closeQuietly(dbSession);
- IOUtils.closeQuietly(writer);
- }
- return writer.toString();
- }
-
- private Map<String, User> getIssueUsersByLogin(Issue issue) {
- Map<String, User> usersByLogin = Maps.newHashMap();
- String assignee = issue.assignee();
- if (assignee != null) {
- usersByLogin.put(assignee, userIndex.getByLogin(assignee));
- }
- String reporter = issue.reporter();
- if (reporter != null) {
- usersByLogin.put(reporter, userIndex.getByLogin(reporter));
- }
- return usersByLogin;
- }
-
- private enum ActionToKey implements Function<Action, String> {
- INSTANCE;
-
- @Override
- public String apply(@Nonnull Action input) {
- return input.key();
- }
- }
-
private enum MatchIssueFilterParameters implements Predicate<Map.Entry<String, Object>> {
INSTANCE;
import org.sonar.server.issue.IssueService;
import org.sonar.server.user.UserSession;
+import static com.google.common.base.Strings.emptyToNull;
+
public class AssignAction implements IssuesWsAction {
public static final String ASSIGN_ACTION = "assign";
@Override
public void handle(Request request, Response response) throws Exception {
- String assignee = request.param("assignee");
+ String assignee = emptyToNull(request.param("assignee"));
if ("_me".equals(assignee) || BooleanUtils.isTrue(request.paramAsBoolean("me"))) {
// Permission is currently checked by IssueService. We still
// check that user is authenticated in order to get his login.
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue.ws;
+
+import org.sonar.api.rule.RuleKey;
+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.issue.DefaultIssue;
+import org.sonar.server.issue.IssueService;
+
+public class CreateAction implements IssuesWsAction {
+
+ public static final String ACTION = "create";
+
+ private final IssueService issueService;
+ private final OperationResponseWriter responseWriter;
+
+ public CreateAction(IssueService issueService, OperationResponseWriter responseWriter) {
+ this.issueService = issueService;
+ this.responseWriter = responseWriter;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ WebService.NewAction action = controller.createAction(ACTION)
+ .setDescription("Create a manual issue. Requires authentication and Browse permission on project")
+ .setSince("3.6")
+ .setHandler(this)
+ .setPost(true);
+
+ action.createParam("component")
+ .setDescription("Key of the component on which to log the issue")
+ .setRequired(true)
+ .setExampleValue("org.apache.struts:struts:org.apache.struts.Action");
+ action.createParam("rule")
+ .setDescription("Manual rule key")
+ .setRequired(true)
+ .setExampleValue("manual:performance");
+ action.createParam("severity")
+ .setDescription("Severity of the issue")
+ .setExampleValue(Severity.BLOCKER + "," + Severity.CRITICAL)
+ .setPossibleValues(Severity.ALL);
+ action.createParam("line")
+ .setDescription("Line on which to log the issue. " +
+ "If no line is specified, the issue is attached to the component and not to a specific line")
+ .setExampleValue("15");
+ action.createParam("message")
+ .setDescription("Description of the issue")
+ .setExampleValue("blabla...");
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ // required parameters
+ String componentKey = request.mandatoryParam("component");
+ RuleKey ruleKey = RuleKey.parse(request.mandatoryParam("rule"));
+
+ DefaultIssue issue = issueService.createManualIssue(componentKey, ruleKey,
+ request.paramAsInt("line"),
+ request.param("message"),
+ request.param("severity"),
+ null);
+
+ responseWriter.write(issue.key(), request, response);
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue.ws;
+
+import org.sonar.api.issue.DefaultTransitions;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.issue.IssueService;
+
+public class DoTransitionAction implements IssuesWsAction {
+
+ public static final String ACTION = "do_transition";
+
+ private final IssueService issueService;
+ private final OperationResponseWriter responseWriter;
+
+ public DoTransitionAction(IssueService issueService, OperationResponseWriter responseWriter) {
+ this.issueService = issueService;
+ this.responseWriter = responseWriter;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ WebService.NewAction action = controller.createAction(ACTION)
+ .setDescription("Do workflow transition on an issue. Requires authentication and Browse permission on project")
+ .setSince("3.6")
+ .setHandler(this)
+ .setPost(true);
+
+ action.createParam("issue")
+ .setDescription("Key of the issue")
+ .setRequired(true)
+ .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
+ action.createParam("transition")
+ .setDescription("Transition")
+ .setRequired(true)
+ .setPossibleValues(DefaultTransitions.ALL);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ String key = request.mandatoryParam("issue");
+ issueService.doTransition(key, request.mandatoryParam("transition"));
+
+ responseWriter.write(key, request, response);
+ }
+}
package org.sonar.server.issue.ws;
import java.util.List;
-import org.sonar.api.server.ServerSide;
import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.action.Action;
+import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.workflow.Transition;
-import org.sonar.server.issue.ActionService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.user.UserSession;
public class IssueActionsWriter {
private final IssueService issueService;
- private final ActionService actionService;
private final UserSession userSession;
- public IssueActionsWriter(IssueService issueService, ActionService actionService, UserSession userSession) {
+ public IssueActionsWriter(IssueService issueService, UserSession userSession) {
this.issueService = issueService;
- this.actionService = actionService;
this.userSession = userSession;
}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue.ws;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.component.ComponentDto;
-
-import static com.google.common.collect.Maps.newHashMap;
-
-/**
- * This class computes some collections of {@link ComponentDto}s used to serialize issues.
- */
-public class IssueComponentHelper {
-
- private final DbClient dbClient;
-
- public IssueComponentHelper(DbClient dbClient) {
- this.dbClient = dbClient;
- }
-
- public Map<String, ComponentDto> prepareComponentsAndProjects(Set<String> projectUuids, Set<String> componentUuids, Map<String, ComponentDto> componentsByUuid,
- Collection<ComponentDto> componentDtos, List<ComponentDto> projectDtos, DbSession session) {
- Map<String, ComponentDto> projectsByComponentUuid;
- List<ComponentDto> fileDtos = dbClient.componentDao().selectByUuids(session, componentUuids);
- List<ComponentDto> subProjectDtos = dbClient.componentDao().selectSubProjectsByComponentUuids(session, componentUuids);
- componentDtos.addAll(fileDtos);
- componentDtos.addAll(subProjectDtos);
- for (ComponentDto component : componentDtos) {
- projectUuids.add(component.projectUuid());
- }
- projectDtos.addAll(dbClient.componentDao().selectByUuids(session, projectUuids));
- componentDtos.addAll(projectDtos);
-
- for (ComponentDto componentDto : componentDtos) {
- componentsByUuid.put(componentDto.uuid(), componentDto);
- }
-
- projectsByComponentUuid = getProjectsByComponentUuid(componentDtos, projectDtos);
- return projectsByComponentUuid;
- }
-
- private Map<String, ComponentDto> getProjectsByComponentUuid(Collection<ComponentDto> components, Collection<ComponentDto> projects) {
- Map<String, ComponentDto> projectsByUuid = buildProjectsByUuid(projects);
- return buildProjectsByComponentUuid(components, projectsByUuid);
- }
-
- private static Map<String, ComponentDto> buildProjectsByUuid(Collection<ComponentDto> projects) {
- Map<String, ComponentDto> projectsByUuid = newHashMap();
- for (ComponentDto project : projects) {
- if (project == null) {
- throw new IllegalStateException("Found a null project in issues");
- }
- if (project.uuid() == null) {
- throw new IllegalStateException("Project has no UUID: " + project.getKey());
- }
- projectsByUuid.put(project.uuid(), project);
- }
- return projectsByUuid;
- }
-
- private static Map<String, ComponentDto> buildProjectsByComponentUuid(Collection<ComponentDto> components, Map<String, ComponentDto> projectsByUuid) {
- Map<String, ComponentDto> projectsByComponentUuid = newHashMap();
- for (ComponentDto component : components) {
- if (component.uuid() == null) {
- throw new IllegalStateException("Component has no UUID: " + component.getKey());
- }
- if (!projectsByUuid.containsKey(component.projectUuid())) {
- throw new IllegalStateException("Project cannot be found for component: " + component.getKey() + " / " + component.uuid());
- }
- projectsByComponentUuid.put(component.uuid(), projectsByUuid.get(component.projectUuid()));
- }
- return projectsByComponentUuid;
- }
-}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.issue.ws;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.issue.ActionPlan;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.IssueComment;
-import org.sonar.api.user.User;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.Duration;
-import org.sonar.api.utils.Durations;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.core.issue.DefaultIssueComment;
-import org.sonar.markdown.Markdown;
-import org.sonar.server.user.UserSession;
-import org.sonar.server.ws.JsonWriterUtils;
-
-import static org.sonar.server.ws.JsonWriterUtils.writeIfNeeded;
-
-public class IssueJsonWriter {
-
- private static final String FIELD_KEY = "key";
- private static final String FIELD_COMPONENT = "component";
- private static final String FIELD_COMPONENT_ID = "componentId";
- private static final String FIELD_PROJECT = "project";
- private static final String FIELD_SUB_PROJECT = "subProject";
- private static final String FIELD_RULE = "rule";
- private static final String FIELD_STATUS = "status";
- private static final String FIELD_RESOLUTION = "resolution";
- private static final String FIELD_AUTHOR = "author";
- private static final String FIELD_REPORTER = "reporter";
- private static final String FIELD_ASSIGNEE = "assignee";
- private static final String FIELD_DEBT = "debt";
- private static final String FIELD_LINE = "line";
- private static final String FIELD_MESSAGE = "message";
- private static final String FIELD_SEVERITY = "severity";
- private static final String FIELD_ACTION_PLAN = "actionPlan";
- private static final String FIELD_CREATION_DATE = "creationDate";
- private static final String FIELD_UPDATE_DATE = "updateDate";
- private static final String FIELD_CLOSE_DATE = "closeDate";
- private static final String FIELD_TAGS = "tags";
- private static final String FIELD_COMMENTS = "comments";
- private static final String FIELD_ATTRIBUTES = "attr";
- public static final String FIELD_ACTIONS = "actions";
- public static final String FIELD_TRANSITIONS = "transitions";
- public static final String FIELD_ACTION_PLAN_NAME = "actionPlanName";
-
- public static final Set<String> EXTRA_FIELDS = ImmutableSet.of(
- FIELD_ACTIONS, FIELD_TRANSITIONS, FIELD_ACTION_PLAN_NAME);
-
- public static final Set<String> SELECTABLE_FIELDS = ImmutableSet.of(FIELD_COMPONENT, FIELD_PROJECT, FIELD_SUB_PROJECT, FIELD_RULE, FIELD_STATUS, FIELD_RESOLUTION, FIELD_AUTHOR,
- FIELD_REPORTER, FIELD_ASSIGNEE, FIELD_DEBT, FIELD_LINE, FIELD_MESSAGE, FIELD_SEVERITY, FIELD_ACTION_PLAN, FIELD_CREATION_DATE, FIELD_UPDATE_DATE, FIELD_CLOSE_DATE,
- FIELD_COMPONENT_ID, FIELD_TAGS, FIELD_COMMENTS, FIELD_ATTRIBUTES, FIELD_ACTIONS, FIELD_TRANSITIONS, FIELD_ACTION_PLAN_NAME);
-
- private static final List<String> SELECTABLE_MINUS_EXTRAS = ImmutableList.copyOf(Sets.difference(SELECTABLE_FIELDS, EXTRA_FIELDS));
-
- private final Durations durations;
- private final UserSession userSession;
- private final IssueActionsWriter actionsWriter;
-
- public IssueJsonWriter(Durations durations, UserSession userSession, IssueActionsWriter actionsWriter) {
- this.durations = durations;
- this.userSession = userSession;
- this.actionsWriter = actionsWriter;
- }
-
- public void write(JsonWriter json, Issue issue, Map<String, User> usersByLogin, Map<String, ComponentDto> componentsByUuid,
- Map<String, ComponentDto> projectsByComponentUuid, Multimap<String, DefaultIssueComment> commentsByIssues, Map<String, ActionPlan> actionPlanByKeys,
- @Nullable List<String> selectedFields) {
-
- List<String> fields = useDefaultFieldsIfNotSpecified(selectedFields);
-
- json.beginObject();
-
- String actionPlanKey = issue.actionPlanKey();
- ComponentDto file = componentsByUuid.get(issue.componentUuid());
- ComponentDto project = null;
- ComponentDto subProject = null;
- if (file != null) {
- project = projectsByComponentUuid.get(file.uuid());
- if (!file.projectUuid().equals(file.moduleUuid())) {
- subProject = componentsByUuid.get(file.moduleUuid());
- }
- }
- Duration debt = issue.debt();
- Date updateDate = issue.updateDate();
-
- json.prop(FIELD_KEY, issue.key());
- JsonWriterUtils.writeIfNeeded(json, file != null ? file.getKey() : null, FIELD_COMPONENT, fields);
- // Only used for the compatibility with the Issues Java WS Client <= 4.4 used by Eclipse
- writeIfNeeded(json, file != null ? file.getId() : null, FIELD_COMPONENT_ID, fields);
- writeIfNeeded(json, project != null ? project.getKey() : null, FIELD_PROJECT, fields);
- writeIfNeeded(json, subProject != null ? subProject.getKey() : null, FIELD_SUB_PROJECT, fields);
- writeIfNeeded(json, issue.ruleKey().toString(), FIELD_RULE, fields);
- writeIfNeeded(json, issue.status(), FIELD_STATUS, fields);
- writeIfNeeded(json, issue.resolution(), FIELD_RESOLUTION, fields);
- writeIfNeeded(json, issue.severity(), FIELD_SEVERITY, fields);
- writeIfNeeded(json, issue.message(), FIELD_MESSAGE, fields);
- writeIfNeeded(json, issue.line(), FIELD_LINE, fields);
- writeIfNeeded(json, debt != null ? durations.encode(debt) : null, FIELD_DEBT, fields);
- writeIfNeeded(json, issue.assignee(), FIELD_ASSIGNEE, fields);
- writeIfNeeded(json, issue.reporter(), FIELD_REPORTER, fields);
- writeIfNeeded(json, issue.authorLogin(), FIELD_AUTHOR, fields);
- writeIfNeeded(json, actionPlanKey, FIELD_ACTION_PLAN, fields);
- writeIfNeeded(json, isoDate(issue.creationDate()), FIELD_CREATION_DATE, fields);
- writeIfNeeded(json, isoDate(updateDate), FIELD_UPDATE_DATE, fields);
- writeIfNeeded(json, isoDate(issue.closeDate()), FIELD_CLOSE_DATE, fields);
-
- if (JsonWriterUtils.isFieldNeeded(FIELD_TAGS, fields)) {
- writeTags(issue, json);
- }
- if (JsonWriterUtils.isFieldNeeded(FIELD_COMMENTS, fields)) {
- writeIssueComments(commentsByIssues.get(issue.key()), usersByLogin, json);
- }
- if (JsonWriterUtils.isFieldNeeded(FIELD_ATTRIBUTES, fields)) {
- writeIssueAttributes(issue, json);
- }
- writeIssueExtraFields(issue, actionPlanByKeys, fields, json);
- json.endObject();
- }
-
- private List<String> useDefaultFieldsIfNotSpecified(List<String> selectedFields) {
- List<String> fields = Lists.newArrayList();
- if (selectedFields == null || selectedFields.isEmpty()) {
- fields.addAll(SELECTABLE_MINUS_EXTRAS);
- } else {
- fields.addAll(selectedFields);
- }
- return fields;
- }
-
- @CheckForNull
- private static String isoDate(@Nullable Date date) {
- if (date != null) {
- return DateUtils.formatDateTime(date);
- }
- return null;
- }
-
- private static void writeTags(Issue issue, JsonWriter json) {
- Collection<String> tags = issue.tags();
- if (tags != null && !tags.isEmpty()) {
- json.name(FIELD_TAGS).beginArray();
- for (String tag : tags) {
- json.value(tag);
- }
- json.endArray();
- }
- }
-
- private void writeIssueComments(Collection<DefaultIssueComment> issueComments, Map<String, User> usersByLogin, JsonWriter json) {
- if (!issueComments.isEmpty()) {
- json.name(FIELD_COMMENTS).beginArray();
- String login = userSession.getLogin();
- for (IssueComment comment : issueComments) {
- String userLogin = comment.userLogin();
- User user = userLogin != null ? usersByLogin.get(userLogin) : null;
- json.beginObject()
- .prop("key", comment.key())
- .prop("login", comment.userLogin())
- .prop("email", user != null ? user.email() : null)
- .prop("userName", user != null ? user.name() : null)
- .prop("htmlText", Markdown.convertToHtml(comment.markdownText()))
- .prop("markdown", comment.markdownText())
- .prop("updatable", login != null && login.equals(userLogin))
- .prop("createdAt", DateUtils.formatDateTime(comment.createdAt()))
- .endObject();
- }
- json.endArray();
- }
- }
-
- private static void writeIssueAttributes(Issue issue, JsonWriter json) {
- if (!issue.attributes().isEmpty()) {
- json.name(FIELD_ATTRIBUTES).beginObject();
- for (Map.Entry<String, String> entry : issue.attributes().entrySet()) {
- json.prop(entry.getKey(), entry.getValue());
- }
- json.endObject();
- }
- }
-
- private void writeIssueExtraFields(Issue issue, Map<String, ActionPlan> actionPlanByKeys,
- @Nullable List<String> fields, JsonWriter json) {
- if (JsonWriterUtils.isFieldNeeded(FIELD_ACTIONS, fields)) {
- actionsWriter.writeActions(issue, json);
- }
-
- if (JsonWriterUtils.isFieldNeeded(FIELD_TRANSITIONS, fields)) {
- actionsWriter.writeTransitions(issue, json);
- }
-
- if (JsonWriterUtils.isFieldNeeded(FIELD_ACTION_PLAN_NAME, fields)) {
- writeActionPlanName(issue, actionPlanByKeys, json);
- }
- }
-
- private void writeActionPlanName(Issue issue, Map<String, ActionPlan> actionPlanByKeys, JsonWriter json) {
- String actionPlanKey = issue.actionPlanKey();
- if (actionPlanKey != null) {
- ActionPlan actionPlan = actionPlanByKeys.get(actionPlanKey);
- json.prop(FIELD_ACTION_PLAN_NAME, actionPlan != null ? actionPlan.name() : null);
- }
- }
-}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.issue.ws;
+
+import org.sonar.core.platform.Module;
+
+public class IssueWsModule extends Module {
+ @Override
+ protected void configureModule() {
+ add(
+ IssuesWs.class,
+ SearchResponseLoader.class,
+ SearchResponseFormat.class,
+ OperationResponseWriter.class,
+ AssignAction.class,
+ CreateAction.class,
+ DoTransitionAction.class,
+ PlanAction.class,
+ ShowAction.class,
+ SearchAction.class,
+ SetSeverityAction.class,
+ TagsAction.class,
+ SetTagsAction.class,
+ ComponentTagsAction.class,
+ IssueActionsWriter.class,
+ AuthorsAction.class);
+ }
+}
public static final String API_ENDPOINT = "api/issues";
public static final String CHANGELOG_ACTION = "changelog";
- public static final String ASSIGN_ACTION = "assign";
public static final String ADD_COMMENT_ACTION = "add_comment";
public static final String DELETE_COMMENT_ACTION = "delete_comment";
public static final String EDIT_COMMENT_ACTION = "edit_comment";
- public static final String SET_SEVERITY_ACTION = "set_severity";
- public static final String PLAN_ACTION = "plan";
- public static final String DO_TRANSITION_ACTION = "do_transition";
public static final String TRANSITIONS_ACTION = "transitions";
- public static final String CREATE_ACTION = "create";
- public static final String DO_ACTION_ACTION = "do_action";
public static final String BULK_CHANGE_ACTION = "bulk_change";
private final IssuesWsAction[] actions;
defineAddCommentAction(controller);
defineDeleteCommentAction(controller);
defineEditCommentAction(controller);
- defineSetSeverityAction(controller);
- definePlanAction(controller);
- defineDoTransitionAction(controller);
defineTransitionsAction(controller);
- defineCreateAction(controller);
- defineDoActionAction(controller);
defineBulkChangeAction(controller);
}
RailsHandler.addFormatParam(action);
}
- private static void defineSetSeverityAction(NewController controller) {
- WebService.NewAction action = controller.createAction(SET_SEVERITY_ACTION)
- .setDescription("Change severity. Requires authentication and Browse permission on project")
- .setSince("3.6")
- .setHandler(RailsHandler.INSTANCE)
- .setPost(true);
-
- action.createParam("issue")
- .setDescription("Key of the issue")
- .setRequired(true)
- .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
- action.createParam("severity")
- .setDescription("New severity")
- .setExampleValue(Severity.BLOCKER)
- .setPossibleValues(Severity.ALL);
- RailsHandler.addFormatParam(action);
- }
-
- private static void definePlanAction(NewController controller) {
- WebService.NewAction action = controller.createAction(PLAN_ACTION)
- .setDescription("Plan/Unplan an issue. Requires authentication and Browse permission on project")
- .setSince("3.6")
- .setHandler(RailsHandler.INSTANCE)
- .setPost(true);
-
- action.createParam("issue")
- .setDescription("Key of the issue")
- .setRequired(true)
- .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
- action.createParam("plan")
- .setDescription("Key of the action plan")
- .setExampleValue("3f19de90-1521-4482-a737-a311758ff513");
- RailsHandler.addFormatParam(action);
- }
-
- private static void defineDoTransitionAction(NewController controller) {
- WebService.NewAction action = controller.createAction(DO_TRANSITION_ACTION)
- .setDescription("Do workflow transition on an issue. Requires authentication and Browse permission on project")
- .setSince("3.6")
- .setHandler(RailsHandler.INSTANCE)
- .setPost(true);
-
- action.createParam("issue")
- .setDescription("Key of the issue")
- .setRequired(true)
- .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
- action.createParam("transition")
- .setDescription("Transition")
- .setExampleValue("reopen")
- .setPossibleValues(DefaultTransitions.ALL);
- RailsHandler.addFormatParam(action);
- }
-
private static void defineTransitionsAction(NewController controller) {
WebService.NewAction action = controller.createAction(TRANSITIONS_ACTION)
.setDescription("Get Possible Workflow Transitions for an Issue. Requires Browse permission on project")
.setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
}
- private static void defineCreateAction(NewController controller) {
- WebService.NewAction action = controller.createAction(CREATE_ACTION)
- .setDescription("Create a manual issue. Requires authentication and Browse permission on project")
- .setSince("3.6")
- .setHandler(RailsHandler.INSTANCE)
- .setPost(true);
-
- action.createParam("component")
- .setDescription("Key of the component on which to log the issue")
- .setRequired(true)
- .setExampleValue("org.apache.struts:struts:org.apache.struts.Action");
- action.createParam("rule")
- .setDescription("Manual rule key")
- .setRequired(true)
- .setExampleValue("manual:performance");
- action.createParam("severity")
- .setDescription("Severity of the issue")
- .setExampleValue(Severity.BLOCKER + "," + Severity.CRITICAL)
- .setPossibleValues(Severity.ALL);
- action.createParam("line")
- .setDescription("Line on which to log the issue. " +
- "If no line is specified, the issue is attached to the component and not to a specific line")
- .setExampleValue("15");
- action.createParam("message")
- .setDescription("Description of the issue")
- .setExampleValue("blabla...");
- RailsHandler.addFormatParam(action);
- }
-
- private static void defineDoActionAction(NewController controller) {
- WebService.NewAction action = controller.createAction(DO_ACTION_ACTION)
- .setDescription("Do workflow transition on an issue. Requires authentication and Browse permission on project")
- .setSince("3.6")
- .setHandler(RailsHandler.INSTANCE)
- .setPost(true);
-
- action.createParam("issue")
- .setDescription("Key of the issue")
- .setRequired(true)
- .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
- action.createParam("actionKey")
- .setDescription("Action to perform")
- .setExampleValue("link-to-jira");
- RailsHandler.addFormatParam(action);
- }
-
private static void defineBulkChangeAction(NewController controller) {
WebService.NewAction action = controller.createAction(BULK_CHANGE_ACTION)
.setDescription("Bulk change on issues. Requires authentication and User role on project(s)")
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue.ws;
+
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.server.issue.IssueService;
+
+import static com.google.common.base.Strings.emptyToNull;
+
+public class PlanAction implements IssuesWsAction {
+
+ public static final String ACTION = "plan";
+
+ private final IssueService issueService;
+ private final OperationResponseWriter responseWriter;
+
+ public PlanAction(IssueService issueService, OperationResponseWriter responseWriter) {
+ this.issueService = issueService;
+ this.responseWriter = responseWriter;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ WebService.NewAction action = controller.createAction(ACTION)
+ .setDescription("Plan/Unplan an issue. Requires authentication and Browse permission on project")
+ .setSince("3.6")
+ .setHandler(this)
+ .setPost(true);
+
+ action.createParam("issue")
+ .setDescription("Key of the issue")
+ .setRequired(true)
+ .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
+ action.createParam("plan")
+ .setDescription("Key of the action plan. Absent value removes the current plan.")
+ .setExampleValue("3f19de90-1521-4482-a737-a311758ff513");
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ String key = request.mandatoryParam("issue");
+ issueService.plan(key, emptyToNull(request.param("plan")));
+
+ responseWriter.write(key, request, response);
+ }
+}
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.issue.ws;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
-import com.google.common.io.Resources;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import javax.annotation.Nullable;
-import org.sonar.api.issue.Issue;
-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.api.server.ws.WebService.Param;
-import org.sonar.api.utils.Paging;
-import org.sonar.core.rule.RuleKeyFunctions;
-import org.sonar.server.es.Facets;
-import org.sonar.server.es.SearchOptions;
-import org.sonar.server.es.SearchResult;
-import org.sonar.server.issue.IssueQuery;
-import org.sonar.server.issue.IssueQueryService;
-import org.sonar.server.issue.IssueService;
-import org.sonar.server.issue.filter.IssueFilterParameters;
-import org.sonar.server.issue.index.IssueDoc;
-import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.user.UserSession;
-import org.sonar.server.ws.WsUtils;
-import org.sonarqube.ws.Issues;
-
-import static com.google.common.collect.FluentIterable.from;
-import static com.google.common.collect.Iterables.concat;
-import static java.util.Collections.singletonList;
-
-public class Search2Action 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 ADDITIONAL_FIELDS = "additionalFields";
- public static final String SEARCH_ACTION = "search2";
-
- private final UserSession userSession;
- private final IssueService service;
- private final IssueQueryService issueQueryService;
- private final SearchResponseLoader searchResponseLoader;
- private final SearchResponseFormat searchResponseFormat;
-
- public Search2Action(UserSession userSession, IssueService service, IssueQueryService issueQueryService,
- SearchResponseLoader searchResponseLoader, SearchResponseFormat searchResponseFormat) {
- this.userSession = userSession;
- this.service = service;
- this.issueQueryService = issueQueryService;
- this.searchResponseLoader = searchResponseLoader;
- this.searchResponseFormat = searchResponseFormat;
- }
-
- @Override
- public void define(WebService.NewController controller) {
- WebService.NewAction action = controller
- .createAction(SEARCH_ACTION)
- .setHandler(this)
- .setDescription(
- "Search for issues. Requires Browse permission on project(s)")
- .setSince("3.6")
- .setResponseExample(Resources.getResource(this.getClass(), "example-search.json"));
-
- action.addPagingParams(100);
- action.createParam(Param.FACETS)
- .setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.")
- .setPossibleValues(IssueIndex.SUPPORTED_FACETS);
- action.createParam(IssueFilterParameters.FACET_MODE)
- .setDefaultValue(IssueFilterParameters.FACET_MODE_COUNT)
- .setDescription("Choose the returned value for facet items, either count of issues or sum of debt.")
- .setPossibleValues(IssueFilterParameters.FACET_MODE_COUNT, IssueFilterParameters.FACET_MODE_DEBT);
- action.addSortParams(IssueQuery.SORTS, null, true);
- action.createParam(ADDITIONAL_FIELDS)
- .setDescription("Comma-separated list of the optional fields to be returned in response.")
- .setPossibleValues(SearchAdditionalField.possibleValues());
- addComponentRelatedParams(action);
- action.createParam(IssueFilterParameters.ISSUES)
- .setDescription("Comma-separated list of issue keys")
- .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
- action.createParam(IssueFilterParameters.SEVERITIES)
- .setDescription("Comma-separated list of severities")
- .setExampleValue(Severity.BLOCKER + "," + Severity.CRITICAL)
- .setPossibleValues(Severity.ALL);
- action.createParam(IssueFilterParameters.STATUSES)
- .setDescription("Comma-separated list of statuses")
- .setExampleValue(Issue.STATUS_OPEN + "," + Issue.STATUS_REOPENED)
- .setPossibleValues(Issue.STATUSES);
- action.createParam(IssueFilterParameters.RESOLUTIONS)
- .setDescription("Comma-separated list of resolutions")
- .setExampleValue(Issue.RESOLUTION_FIXED + "," + Issue.RESOLUTION_REMOVED)
- .setPossibleValues(Issue.RESOLUTIONS);
- action.createParam(IssueFilterParameters.RESOLVED)
- .setDescription("To match resolved or unresolved issues")
- .setBooleanPossibleValues();
- action.createParam(IssueFilterParameters.RULES)
- .setDescription("Comma-separated list of coding rule keys. Format is <repository>:<rule>")
- .setExampleValue("squid:AvoidCycles");
- action.createParam(IssueFilterParameters.TAGS)
- .setDescription("Comma-separated list of tags.")
- .setExampleValue("security,convention");
- action.createParam(IssueFilterParameters.ACTION_PLANS)
- .setDescription("Comma-separated list of action plan keys (not names)")
- .setExampleValue("3f19de90-1521-4482-a737-a311758ff513");
- action.createParam(IssueFilterParameters.PLANNED)
- .setDescription("To retrieve issues associated to an action plan or not")
- .setBooleanPossibleValues();
- action.createParam(IssueFilterParameters.REPORTERS)
- .setDescription("Comma-separated list of reporter logins")
- .setExampleValue("admin");
- action.createParam(IssueFilterParameters.AUTHORS)
- .setDescription("Comma-separated list of SCM accounts")
- .setExampleValue("torvalds@linux-foundation.org");
- action.createParam(IssueFilterParameters.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(IssueFilterParameters.ASSIGNED)
- .setDescription("To retrieve assigned or unassigned issues")
- .setBooleanPossibleValues();
- action.createParam(IssueFilterParameters.LANGUAGES)
- .setDescription("Comma-separated list of languages. Available since 4.4")
- .setExampleValue("java,js");
- action.createParam(IssueFilterParameters.CREATED_AT)
- .setDescription("To retrieve issues created at a given date. Format: date or datetime ISO formats")
- .setExampleValue("2013-05-01 (or 2013-05-01T13:00:00+0100)");
- action.createParam(IssueFilterParameters.CREATED_AFTER)
- .setDescription("To retrieve issues created after the given date (exclusive). 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(IssueFilterParameters.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(IssueFilterParameters.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)");
- }
-
- private static void addComponentRelatedParams(WebService.NewAction action) {
- action.createParam(IssueFilterParameters.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. " +
- "Using the deprecated components parameter will set this parameter to true.")
- .setBooleanPossibleValues()
- .setDefaultValue("false");
-
- action.createParam(IssueFilterParameters.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. " +
- "If this parameter is set, componentUuids must not be set.")
- .setExampleValue("org.apache.struts:struts:org.apache.struts.Action");
- action.createParam(IssueFilterParameters.COMPONENTS)
- .setDescription("Deprecated since 5.1. If used, will have the same meaning as componentKeys AND onComponentOnly=true.");
- action.createParam(IssueFilterParameters.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. " +
- "If this parameter is set, componentKeys must not be set.")
- .setExampleValue("584a89f2-8037-4f7b-b82c-8b45d2d63fb2");
-
- action.createParam(IssueFilterParameters.COMPONENT_ROOTS)
- .setDescription("Deprecated since 5.1. If used, will have the same meaning as componentKeys AND onComponentOnly=false.");
- action.createParam(IssueFilterParameters.COMPONENT_ROOT_UUIDS)
- .setDescription("Deprecated since 5.1. If used, will have the same meaning as componentUuids AND onComponentOnly=false.");
-
- action.createParam(IssueFilterParameters.PROJECTS)
- .setDescription("Deprecated since 5.1. See projectKeys");
- action.createParam(IssueFilterParameters.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(IssueFilterParameters.PROJECTS)
- .setExampleValue("org.apache.struts:struts:org.apache.struts.Action");
- action.createParam(IssueFilterParameters.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(IssueFilterParameters.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(IssueFilterParameters.DIRECTORIES)
- .setDescription("Since 5.1. 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)
- .setExampleValue("src/main/java/org/sonar/server/");
-
- action.createParam(IssueFilterParameters.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");
- }
-
- @Override
- public final void handle(Request request, Response response) throws Exception {
- // prepare the Elasticsearch request
- SearchOptions options = new SearchOptions();
- options.setPage(request.mandatoryParamAsInt(Param.PAGE), request.mandatoryParamAsInt(Param.PAGE_SIZE));
- options.addFacets(request.paramAsStrings(Param.FACETS));
- EnumSet<SearchAdditionalField> additionalFields = SearchAdditionalField.getFromRequest(request);
- IssueQuery query = issueQueryService.createFromRequest(request);
-
- // execute request
- SearchResult<IssueDoc> result = service.search(query, options);
- List<String> issueKeys = from(result.getDocs()).transform(IssueDocToKey.INSTANCE).toList();
-
- // load the additional information to be returned in response
- SearchResponseLoader.Collector collector = new SearchResponseLoader.Collector(additionalFields, issueKeys);
- collectLoggedInUser(collector);
- collectRequestParams(collector, request);
- Facets facets = null;
- if (!options.getFacets().isEmpty()) {
- facets = result.getFacets();
- // add missing values to facets. For example if assignee "john" and facet on "assignees" are requested, then
- // "john" should always be listed in the facet. If it is not present, then it is added with value zero.
- // This is a constraint from webapp UX.
- completeFacets(facets, options, request);
- collectFacets(collector, facets);
- }
- SearchResponseData data = searchResponseLoader.load(collector, facets);
-
- // format response
-
- // Filter and reorder facets according to the requested ordered names.
- // Must be done after loading of data as the "hidden" facet "debt"
- // can be used to get total debt.
- facets = reorderFacets(facets, options.getFacets());
-
- // FIXME allow long in Paging
- Paging paging = Paging.create(options.getLimit(), options.getPage(), (int) result.getTotal());
- Issues.Search responseBody = searchResponseFormat.formatSearch(additionalFields, data, paging, facets);
- WsUtils.writeProtobuf(responseBody, request, response);
- }
-
- private Facets reorderFacets(@Nullable Facets facets, Collection<String> orderedNames) {
- if (facets == null) {
- return null;
- }
- LinkedHashMap<String, LinkedHashMap<String, Long>> orderedFacets = new LinkedHashMap<>();
- for (String facetName : orderedNames) {
- LinkedHashMap<String, Long> facet = facets.get(facetName);
- if (facet != null) {
- orderedFacets.put(facetName, facet);
- }
- }
- return new Facets(orderedFacets);
- }
-
- private void completeFacets(Facets facets, SearchOptions options, Request request) {
- addMandatoryValuesToFacet(facets, IssueFilterParameters.SEVERITIES, Severity.ALL);
- addMandatoryValuesToFacet(facets, IssueFilterParameters.STATUSES, Issue.STATUSES);
- addMandatoryValuesToFacet(facets, IssueFilterParameters.RESOLUTIONS, concat(singletonList(""), Issue.RESOLUTIONS));
- addMandatoryValuesToFacet(facets, IssueFilterParameters.PROJECT_UUIDS, request.paramAsStrings(IssueFilterParameters.PROJECT_UUIDS));
-
- List<String> assignees = Lists.newArrayList("");
- List<String> assigneesFromRequest = request.paramAsStrings(IssueFilterParameters.ASSIGNEES);
- if (assigneesFromRequest != null) {
- assignees.addAll(assigneesFromRequest);
- assignees.remove(IssueQueryService.LOGIN_MYSELF);
- }
- addMandatoryValuesToFacet(facets, IssueFilterParameters.ASSIGNEES, assignees);
- addMandatoryValuesToFacet(facets, IssueFilterParameters.FACET_ASSIGNED_TO_ME, singletonList(userSession.getLogin()));
- addMandatoryValuesToFacet(facets, IssueFilterParameters.REPORTERS, request.paramAsStrings(IssueFilterParameters.REPORTERS));
- addMandatoryValuesToFacet(facets, IssueFilterParameters.RULES, request.paramAsStrings(IssueFilterParameters.RULES));
- addMandatoryValuesToFacet(facets, IssueFilterParameters.LANGUAGES, request.paramAsStrings(IssueFilterParameters.LANGUAGES));
- addMandatoryValuesToFacet(facets, IssueFilterParameters.TAGS, request.paramAsStrings(IssueFilterParameters.TAGS));
- List<String> actionPlans = Lists.newArrayList("");
- List<String> actionPlansFromRequest = request.paramAsStrings(IssueFilterParameters.ACTION_PLANS);
- if (actionPlansFromRequest != null) {
- actionPlans.addAll(actionPlansFromRequest);
- }
- addMandatoryValuesToFacet(facets, IssueFilterParameters.ACTION_PLANS, actionPlans);
- addMandatoryValuesToFacet(facets, IssueFilterParameters.COMPONENT_UUIDS, request.paramAsStrings(IssueFilterParameters.COMPONENT_UUIDS));
-
- for (String facetName : options.getFacets()) {
- LinkedHashMap<String, Long> buckets = facets.get(facetName);
- if (!IssueFilterParameters.FACET_ASSIGNED_TO_ME.equals(facetName)) {
- if (buckets != null) {
- List<String> requestParams = request.paramAsStrings(facetName);
- if (requestParams != null) {
- for (String param : requestParams) {
- if (!buckets.containsKey(param) && !IssueQueryService.LOGIN_MYSELF.equals(param)) {
- // Prevent appearance of a glitch value due to dedicated parameter for this facet
- buckets.put(param, 0L);
- }
- }
- }
- }
- }
- }
- }
-
- private void addMandatoryValuesToFacet(Facets facets, String facetName, @Nullable Iterable<String> mandatoryValues) {
- Map<String, Long> buckets = facets.get(facetName);
- if (buckets != null && mandatoryValues != null) {
- for (String mandatoryValue : mandatoryValues) {
- if (!buckets.containsKey(mandatoryValue)) {
- buckets.put(mandatoryValue, 0L);
- }
- }
- }
- }
-
- private void collectLoggedInUser(SearchResponseLoader.Collector collector) {
- if (userSession.isLoggedIn()) {
- collector.add(SearchAdditionalField.USERS, userSession.getLogin());
- }
- }
-
- private void collectFacets(SearchResponseLoader.Collector collector, Facets facets) {
- Set<String> facetRules = facets.getBucketKeys(IssueFilterParameters.RULES);
- if (facetRules != null) {
- collector.addAll(SearchAdditionalField.RULES, from(facetRules).transform(RuleKeyFunctions.stringToRuleKey()));
- }
- collector.addProjectUuids(facets.getBucketKeys(IssueFilterParameters.PROJECT_UUIDS));
- collector.addComponentUuids(facets.getBucketKeys(IssueFilterParameters.COMPONENT_UUIDS));
- collector.addComponentUuids(facets.getBucketKeys(IssueFilterParameters.FILE_UUIDS));
- collector.addComponentUuids(facets.getBucketKeys(IssueFilterParameters.MODULE_UUIDS));
- collector.addAll(SearchAdditionalField.USERS, facets.getBucketKeys(IssueFilterParameters.ASSIGNEES));
- collector.addAll(SearchAdditionalField.USERS, facets.getBucketKeys(IssueFilterParameters.REPORTERS));
- collector.addAll(SearchAdditionalField.ACTION_PLANS, facets.getBucketKeys(IssueFilterParameters.ACTION_PLANS));
- }
-
- private void collectRequestParams(SearchResponseLoader.Collector collector, Request request) {
- collector.addProjectUuids(request.paramAsStrings(IssueFilterParameters.PROJECT_UUIDS));
- collector.addComponentUuids(request.paramAsStrings(IssueFilterParameters.FILE_UUIDS));
- collector.addComponentUuids(request.paramAsStrings(IssueFilterParameters.MODULE_UUIDS));
- collector.addComponentUuids(request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOT_UUIDS));
- collector.addAll(SearchAdditionalField.USERS, request.paramAsStrings(IssueFilterParameters.ASSIGNEES));
- collector.addAll(SearchAdditionalField.USERS, request.paramAsStrings(IssueFilterParameters.REPORTERS));
- collector.addAll(SearchAdditionalField.ACTION_PLANS, request.paramAsStrings(IssueFilterParameters.ACTION_PLANS));
- }
-
- private enum IssueDocToKey implements Function<IssueDoc, String> {
- INSTANCE;
- @Override
- public String apply(IssueDoc input) {
- return input.key();
- }
- }
-}
*/
package org.sonar.server.issue.ws;
-import com.google.common.collect.ArrayListMultimap;
+import com.google.common.base.Function;
import com.google.common.collect.Lists;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
import com.google.common.io.Resources;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
+import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import org.apache.commons.lang.BooleanUtils;
-import org.sonar.api.i18n.I18n;
-import org.sonar.api.issue.ActionPlan;
import org.sonar.api.issue.Issue;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.rule.RuleKey;
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.api.server.ws.WebService.Param;
-import org.sonar.api.user.User;
-import org.sonar.api.user.UserFinder;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.core.issue.DefaultIssueComment;
-import org.sonar.db.DbSession;
-import org.sonar.server.component.ws.ComponentJsonWriter;
-import org.sonar.db.DbClient;
+import org.sonar.api.utils.Paging;
+import org.sonar.core.rule.RuleKeyFunctions;
import org.sonar.server.es.Facets;
import org.sonar.server.es.SearchOptions;
import org.sonar.server.es.SearchResult;
import org.sonar.server.issue.IssueQuery;
import org.sonar.server.issue.IssueQueryService;
import org.sonar.server.issue.IssueService;
-import org.sonar.server.issue.actionplan.ActionPlanService;
import org.sonar.server.issue.filter.IssueFilterParameters;
import org.sonar.server.issue.index.IssueDoc;
import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.rule.Rule;
-import org.sonar.server.rule.RuleService;
import org.sonar.server.user.UserSession;
-import org.sonar.server.user.ws.UserJsonWriter;
+import org.sonar.server.ws.WsUtils;
+import org.sonarqube.ws.Issues;
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
-import static com.google.common.collect.Sets.newHashSet;
+import static com.google.common.collect.FluentIterable.from;
+import static com.google.common.collect.Iterables.concat;
+import static java.util.Collections.singletonList;
public class SearchAction implements IssuesWsAction {
- public static final String SEARCH_ACTION = "search";
-
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 ADDITIONAL_FIELDS = "additionalFields";
+ public static final String SEARCH_ACTION = "search";
+ private final UserSession userSession;
private final IssueService service;
-
private final IssueQueryService issueQueryService;
- private final RuleService ruleService;
- private final DbClient dbClient;
- private final ActionPlanService actionPlanService;
- private final UserFinder userFinder;
- private final I18n i18n;
- private final Languages languages;
- private final UserSession userSession;
- private final IssueJsonWriter issueWriter;
- private final UserJsonWriter userWriter;
- private final IssueComponentHelper issueComponentHelper;
- private final ComponentJsonWriter componentWriter;
+ private final SearchResponseLoader searchResponseLoader;
+ private final SearchResponseFormat searchResponseFormat;
- public SearchAction(DbClient dbClient, IssueService service, IssueQueryService issueQueryService,
- RuleService ruleService, ActionPlanService actionPlanService, UserFinder userFinder, I18n i18n, Languages languages,
- UserSession userSession, IssueJsonWriter issueWriter, IssueComponentHelper issueComponentHelper, ComponentJsonWriter componentWriter, UserJsonWriter userWriter) {
- this.dbClient = dbClient;
+ public SearchAction(UserSession userSession, IssueService service, IssueQueryService issueQueryService,
+ SearchResponseLoader searchResponseLoader, SearchResponseFormat searchResponseFormat) {
+ this.userSession = userSession;
this.service = service;
this.issueQueryService = issueQueryService;
- this.ruleService = ruleService;
- this.actionPlanService = actionPlanService;
- this.userFinder = userFinder;
- this.i18n = i18n;
- this.languages = languages;
- this.userSession = userSession;
- this.issueWriter = issueWriter;
- this.userWriter = userWriter;
- this.issueComponentHelper = issueComponentHelper;
- this.componentWriter = componentWriter;
+ this.searchResponseLoader = searchResponseLoader;
+ this.searchResponseFormat = searchResponseFormat;
}
@Override
.createAction(SEARCH_ACTION)
.setHandler(this)
.setDescription(
- "Get a list of issues. Requires Browse permission on project(s)")
+ "Search for issues. Requires Browse permission on project(s)")
.setSince("3.6")
.setResponseExample(Resources.getResource(this.getClass(), "example-search.json"));
action.addPagingParams(100);
- action.createParam(WebService.Param.FACETS)
+ action.createParam(Param.FACETS)
.setDescription("Comma-separated list of the facets to be computed. No facet is computed by default.")
.setPossibleValues(IssueIndex.SUPPORTED_FACETS);
action.createParam(IssueFilterParameters.FACET_MODE)
.setDescription("Choose the returned value for facet items, either count of issues or sum of debt.")
.setPossibleValues(IssueFilterParameters.FACET_MODE_COUNT, IssueFilterParameters.FACET_MODE_DEBT);
action.addSortParams(IssueQuery.SORTS, null, true);
- action.addFieldsParam(IssueJsonWriter.SELECTABLE_FIELDS);
-
+ action.createParam(ADDITIONAL_FIELDS)
+ .setDescription("Comma-separated list of the optional fields to be returned in response.")
+ .setPossibleValues(SearchAdditionalField.possibleValues());
addComponentRelatedParams(action);
action.createParam(IssueFilterParameters.ISSUES)
.setDescription("Comma-separated list of issue keys")
action.createParam(IssueFilterParameters.TAGS)
.setDescription("Comma-separated list of tags.")
.setExampleValue("security,convention");
- action.createParam(IssueFilterParameters.HIDE_RULES)
- .setDescription("To not return rules")
- .setDefaultValue(false)
- .setBooleanPossibleValues();
- action.createParam(IssueFilterParameters.HIDE_COMMENTS)
- .setDescription("To not return comments")
- .setDefaultValue(false)
- .setBooleanPossibleValues();
action.createParam(IssueFilterParameters.ACTION_PLANS)
.setDescription("Comma-separated list of action plan keys (not names)")
.setExampleValue("3f19de90-1521-4482-a737-a311758ff513");
"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("format")
- .setDescription("Only json format is available. This parameter is kept only for backward compatibility and shouldn't be used anymore");
}
private static void addComponentRelatedParams(WebService.NewAction action) {
@Override
public final void handle(Request request, Response response) throws Exception {
+ // prepare the Elasticsearch request
SearchOptions options = new SearchOptions();
- options.setPage(request.mandatoryParamAsInt(WebService.Param.PAGE), request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE));
- options.addFacets(request.paramAsStrings(WebService.Param.FACETS));
-
+ options.setPage(request.mandatoryParamAsInt(Param.PAGE), request.mandatoryParamAsInt(Param.PAGE_SIZE));
+ options.addFacets(request.paramAsStrings(Param.FACETS));
+ EnumSet<SearchAdditionalField> additionalFields = SearchAdditionalField.getFromRequest(request);
IssueQuery query = issueQueryService.createFromRequest(request);
- SearchResult<IssueDoc> result = service.search(query, options);
- JsonWriter json = response.newJsonWriter().beginObject();
- options.writeJson(json, result.getTotal());
- options.writeDeprecatedJson(json, result.getTotal());
+ // execute request
+ SearchResult<IssueDoc> result = service.search(query, options);
+ List<String> issueKeys = from(result.getDocs()).transform(IssueDocToKey.INSTANCE).toList();
- writeResponse(request, result, json);
+ // load the additional information to be returned in response
+ SearchResponseLoader.Collector collector = new SearchResponseLoader.Collector(additionalFields, issueKeys);
+ collectLoggedInUser(collector);
+ collectRequestParams(collector, request);
+ Facets facets = null;
if (!options.getFacets().isEmpty()) {
- writeFacets(request, options, result, json);
- }
- json.endObject().close();
- }
-
- private void writeResponse(Request request, SearchResult<IssueDoc> result, JsonWriter json) {
- Map<String, Long> debtFacet = result.getFacets().get(IssueIndex.DEBT_AGGREGATION_NAME);
- if (debtFacet != null) {
- json.prop("debtTotal", debtFacet.get(Facets.TOTAL));
- }
-
- List<String> issueKeys = newArrayList();
- Set<RuleKey> ruleKeys = newHashSet();
- Set<String> projectUuids = newHashSet();
- Set<String> componentUuids = newHashSet();
- Set<String> actionPlanKeys = newHashSet();
- List<String> userLogins = newArrayList();
- Map<String, User> usersByLogin = newHashMap();
- Map<String, ComponentDto> componentsByUuid = newHashMap();
- Multimap<String, DefaultIssueComment> commentsByIssues = ArrayListMultimap.create();
- Collection<ComponentDto> componentDtos = newHashSet();
- List<ComponentDto> projectDtos = Lists.newArrayList();
- Map<String, ComponentDto> projectsByComponentUuid = newHashMap();
-
- for (IssueDoc issueDoc : result.getDocs()) {
- issueKeys.add(issueDoc.key());
- ruleKeys.add(issueDoc.ruleKey());
- projectUuids.add(issueDoc.projectUuid());
- componentUuids.add(issueDoc.componentUuid());
- actionPlanKeys.add(issueDoc.actionPlanKey());
- if (issueDoc.reporter() != null) {
- userLogins.add(issueDoc.reporter());
- }
- if (issueDoc.assignee() != null) {
- userLogins.add(issueDoc.assignee());
- }
+ facets = result.getFacets();
+ // add missing values to facets. For example if assignee "john" and facet on "assignees" are requested, then
+ // "john" should always be listed in the facet. If it is not present, then it is added with value zero.
+ // This is a constraint from webapp UX.
+ completeFacets(facets, options, request);
+ collectFacets(collector, facets);
}
+ SearchResponseData data = searchResponseLoader.load(collector, facets);
- collectRuleKeys(request, result, ruleKeys);
+ // format response
- collectFacetsData(request, result, projectUuids, componentUuids, userLogins, actionPlanKeys);
+ // Filter and reorder facets according to the requested ordered names.
+ // Must be done after loading of data as the "hidden" facet "debt"
+ // can be used to get total debt.
+ facets = reorderFacets(facets, options.getFacets());
- if (userSession.isLoggedIn()) {
- userLogins.add(userSession.getLogin());
- }
-
- DbSession session = dbClient.openSession(false);
- try {
- if (!BooleanUtils.isTrue(request.paramAsBoolean(IssueFilterParameters.HIDE_COMMENTS))) {
- List<DefaultIssueComment> comments = dbClient.issueChangeDao().selectCommentsByIssues(session, issueKeys);
- for (DefaultIssueComment issueComment : comments) {
- userLogins.add(issueComment.userLogin());
- commentsByIssues.put(issueComment.issueKey(), issueComment);
- }
- }
- usersByLogin = getUsersByLogin(userLogins);
-
- projectsByComponentUuid = issueComponentHelper.prepareComponentsAndProjects(projectUuids, componentUuids, componentsByUuid, componentDtos, projectDtos, session);
-
- writeProjects(json, projectDtos);
- writeComponents(json, componentDtos, projectsByComponentUuid);
- } finally {
- session.close();
- }
-
- Map<String, ActionPlan> actionPlanByKeys = getActionPlanByKeys(actionPlanKeys);
-
- writeIssues(result, commentsByIssues, usersByLogin, actionPlanByKeys, componentsByUuid, projectsByComponentUuid,
- request.paramAsStrings(Param.FIELDS), json);
- writeRules(json, !request.mandatoryParamAsBoolean(IssueFilterParameters.HIDE_RULES) ? ruleService.getByKeys(ruleKeys) : Collections.<Rule>emptyList());
- writeUsers(json, usersByLogin);
- writeActionPlans(json, actionPlanByKeys.values());
- writeLanguages(json);
+ // FIXME allow long in Paging
+ Paging paging = Paging.create(options.getLimit(), options.getPage(), (int) result.getTotal());
+ Issues.Search responseBody = searchResponseFormat.formatSearch(additionalFields, data, paging, facets);
+ WsUtils.writeProtobuf(responseBody, request, response);
}
- private static void collectRuleKeys(Request request, SearchResult<IssueDoc> result, Set<RuleKey> ruleKeys) {
- Set<String> facetRules = result.getFacets().getBucketKeys(IssueFilterParameters.RULES);
- if (facetRules != null) {
- for (String rule : facetRules) {
- ruleKeys.add(RuleKey.parse(rule));
- }
+ private Facets reorderFacets(@Nullable Facets facets, Collection<String> orderedNames) {
+ if (facets == null) {
+ return null;
}
- List<String> rulesFromRequest = request.paramAsStrings(IssueFilterParameters.RULES);
- if (rulesFromRequest != null) {
- for (String ruleKey : rulesFromRequest) {
- ruleKeys.add(RuleKey.parse(ruleKey));
+ LinkedHashMap<String, LinkedHashMap<String, Long>> orderedFacets = new LinkedHashMap<>();
+ for (String facetName : orderedNames) {
+ LinkedHashMap<String, Long> facet = facets.get(facetName);
+ if (facet != null) {
+ orderedFacets.put(facetName, facet);
}
}
+ return new Facets(orderedFacets);
}
- protected void writeFacets(Request request, SearchOptions options, SearchResult<IssueDoc> results, JsonWriter json) {
- addMandatoryFacetValues(results, IssueFilterParameters.SEVERITIES, Severity.ALL);
- addMandatoryFacetValues(results, IssueFilterParameters.STATUSES, Issue.STATUSES);
- List<String> resolutions = Lists.newArrayList("");
- resolutions.addAll(Issue.RESOLUTIONS);
- addMandatoryFacetValues(results, IssueFilterParameters.RESOLUTIONS, resolutions);
- addMandatoryFacetValues(results, IssueFilterParameters.PROJECT_UUIDS, request.paramAsStrings(IssueFilterParameters.PROJECT_UUIDS));
+ private void completeFacets(Facets facets, SearchOptions options, Request request) {
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.SEVERITIES, Severity.ALL);
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.STATUSES, Issue.STATUSES);
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.RESOLUTIONS, concat(singletonList(""), Issue.RESOLUTIONS));
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.PROJECT_UUIDS, request.paramAsStrings(IssueFilterParameters.PROJECT_UUIDS));
List<String> assignees = Lists.newArrayList("");
List<String> assigneesFromRequest = request.paramAsStrings(IssueFilterParameters.ASSIGNEES);
assignees.addAll(assigneesFromRequest);
assignees.remove(IssueQueryService.LOGIN_MYSELF);
}
- addMandatoryFacetValues(results, IssueFilterParameters.ASSIGNEES, assignees);
- addMandatoryFacetValues(results, IssueFilterParameters.FACET_ASSIGNED_TO_ME, Arrays.asList(userSession.getLogin()));
- addMandatoryFacetValues(results, IssueFilterParameters.REPORTERS, request.paramAsStrings(IssueFilterParameters.REPORTERS));
- addMandatoryFacetValues(results, IssueFilterParameters.RULES, request.paramAsStrings(IssueFilterParameters.RULES));
- addMandatoryFacetValues(results, IssueFilterParameters.LANGUAGES, request.paramAsStrings(IssueFilterParameters.LANGUAGES));
- addMandatoryFacetValues(results, IssueFilterParameters.TAGS, request.paramAsStrings(IssueFilterParameters.TAGS));
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.ASSIGNEES, assignees);
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.FACET_ASSIGNED_TO_ME, singletonList(userSession.getLogin()));
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.REPORTERS, request.paramAsStrings(IssueFilterParameters.REPORTERS));
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.RULES, request.paramAsStrings(IssueFilterParameters.RULES));
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.LANGUAGES, request.paramAsStrings(IssueFilterParameters.LANGUAGES));
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.TAGS, request.paramAsStrings(IssueFilterParameters.TAGS));
List<String> actionPlans = Lists.newArrayList("");
List<String> actionPlansFromRequest = request.paramAsStrings(IssueFilterParameters.ACTION_PLANS);
if (actionPlansFromRequest != null) {
actionPlans.addAll(actionPlansFromRequest);
}
- addMandatoryFacetValues(results, IssueFilterParameters.ACTION_PLANS, actionPlans);
- addMandatoryFacetValues(results, IssueFilterParameters.COMPONENT_UUIDS, request.paramAsStrings(IssueFilterParameters.COMPONENT_UUIDS));
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.ACTION_PLANS, actionPlans);
+ addMandatoryValuesToFacet(facets, IssueFilterParameters.COMPONENT_UUIDS, request.paramAsStrings(IssueFilterParameters.COMPONENT_UUIDS));
- json.name("facets").beginArray();
for (String facetName : options.getFacets()) {
- json.beginObject();
- json.prop("property", facetName);
- json.name("values").beginArray();
- LinkedHashMap<String, Long> buckets = results.getFacets().get(facetName);
- if (buckets != null) {
- Set<String> itemsFromFacets = Sets.newHashSet();
- for (Map.Entry<String, Long> bucket : buckets.entrySet()) {
- itemsFromFacets.add(bucket.getKey());
- json.beginObject();
- json.prop("val", bucket.getKey());
- json.prop("count", bucket.getValue());
- json.endObject();
- }
- // Prevent appearance of a glitch value due to dedicated parameter for this facet
- if (!IssueFilterParameters.FACET_ASSIGNED_TO_ME.equals(facetName)) {
- addZeroFacetsForSelectedItems(request, facetName, itemsFromFacets, json);
+ LinkedHashMap<String, Long> buckets = facets.get(facetName);
+ if (!IssueFilterParameters.FACET_ASSIGNED_TO_ME.equals(facetName)) {
+ if (buckets != null) {
+ List<String> requestParams = request.paramAsStrings(facetName);
+ if (requestParams != null) {
+ for (String param : requestParams) {
+ if (!buckets.containsKey(param) && !IssueQueryService.LOGIN_MYSELF.equals(param)) {
+ // Prevent appearance of a glitch value due to dedicated parameter for this facet
+ buckets.put(param, 0L);
+ }
+ }
+ }
}
}
- json.endArray().endObject();
- }
- json.endArray();
- }
-
- private void collectFacetsData(Request request, SearchResult<IssueDoc> result, Set<String> projectUuids, Set<String> componentUuids, List<String> userLogins,
- Set<String> actionPlanKeys) {
- collectBucketKeys(result, IssueFilterParameters.PROJECT_UUIDS, projectUuids);
- collectParameterValues(request, IssueFilterParameters.PROJECT_UUIDS, projectUuids);
-
- collectBucketKeys(result, IssueFilterParameters.COMPONENT_UUIDS, componentUuids);
- collectParameterValues(request, IssueFilterParameters.COMPONENT_UUIDS, componentUuids);
- collectBucketKeys(result, IssueFilterParameters.FILE_UUIDS, componentUuids);
- collectParameterValues(request, IssueFilterParameters.FILE_UUIDS, componentUuids);
-
- collectBucketKeys(result, IssueFilterParameters.MODULE_UUIDS, componentUuids);
- collectParameterValues(request, IssueFilterParameters.MODULE_UUIDS, componentUuids);
- collectParameterValues(request, IssueFilterParameters.COMPONENT_ROOT_UUIDS, componentUuids);
-
- collectBucketKeys(result, IssueFilterParameters.ASSIGNEES, userLogins);
- collectParameterValues(request, IssueFilterParameters.ASSIGNEES, userLogins);
- collectBucketKeys(result, IssueFilterParameters.REPORTERS, userLogins);
- collectParameterValues(request, IssueFilterParameters.REPORTERS, userLogins);
- collectBucketKeys(result, IssueFilterParameters.ACTION_PLANS, actionPlanKeys);
- collectParameterValues(request, IssueFilterParameters.ACTION_PLANS, actionPlanKeys);
- }
-
- private static void collectBucketKeys(SearchResult<IssueDoc> result, String facetName, Collection<String> bucketKeys) {
- bucketKeys.addAll(result.getFacets().getBucketKeys(facetName));
- }
-
- private static void collectParameterValues(Request request, String facetName, Collection<String> facetKeys) {
- Collection<String> paramValues = request.paramAsStrings(facetName);
- if (paramValues != null) {
- facetKeys.addAll(paramValues);
- }
- }
-
- // TODO change to use the RuleMapper
- private void writeRules(JsonWriter json, Collection<Rule> rules) {
- json.name("rules").beginArray();
- for (Rule rule : rules) {
- json.beginObject()
- .prop("key", rule.key().toString())
- .prop("name", rule.name())
- .prop("lang", rule.language())
- .prop("desc", rule.htmlDescription())
- .prop("status", rule.status().toString());
- Language lang = languages.get(rule.language());
- json.prop("langName", lang == null ? null : lang.getName());
- json.endObject();
- }
- json.endArray();
- }
-
- private void writeIssues(SearchResult<IssueDoc> result, Multimap<String, DefaultIssueComment> commentsByIssues, Map<String, User> usersByLogin,
- Map<String, ActionPlan> actionPlanByKeys,
- Map<String, ComponentDto> componentsByUuid, Map<String, ComponentDto> projectsByComponentUuid, @Nullable List<String> fields, JsonWriter json) {
- json.name("issues").beginArray();
-
- for (IssueDoc issue : result.getDocs()) {
- issueWriter.write(json, issue, usersByLogin, componentsByUuid, projectsByComponentUuid, commentsByIssues, actionPlanByKeys, fields);
- }
-
- json.endArray();
- }
-
- private void writeComponents(JsonWriter json, Collection<ComponentDto> components, Map<String, ComponentDto> projectsByComponentUuid) {
- json.name("components").beginArray();
- for (ComponentDto component : components) {
- ComponentDto project = projectsByComponentUuid.get(component.uuid());
- componentWriter.write(json, component, project);
- }
- json.endArray();
- }
-
- private static void writeProjects(JsonWriter json, List<ComponentDto> projects) {
- json.name("projects").beginArray();
- for (ComponentDto project : projects) {
- json.beginObject()
- .prop("uuid", project.uuid())
- .prop("key", project.key())
- .prop("id", project.getId())
- .prop("qualifier", project.qualifier())
- .prop("name", project.name())
- .prop("longName", project.longName())
- .endObject();
}
- json.endArray();
}
- private void writeUsers(JsonWriter json, Map<String, User> usersByLogin) {
- json.name("users").beginArray();
- for (User user : usersByLogin.values()) {
- userWriter.write(json, user);
- }
- json.endArray();
- }
-
- private void writeLanguages(JsonWriter json) {
- json.name("languages").beginArray();
- for (Language language : languages.all()) {
- json.beginObject()
- .prop("key", language.getKey())
- .prop("name", language.getName())
- .endObject();
- }
- json.endArray();
- }
-
- private void writeActionPlans(JsonWriter json, Collection<ActionPlan> plans) {
- if (!plans.isEmpty()) {
- json.name("actionPlans").beginArray();
- for (ActionPlan actionPlan : plans) {
- Date deadLine = actionPlan.deadLine();
- Date updatedAt = actionPlan.updatedAt();
-
- json.beginObject()
- .prop("key", actionPlan.key())
- .prop("name", actionPlan.name())
- .prop("status", actionPlan.status())
- .prop("project", actionPlan.projectKey())
- .prop("userLogin", actionPlan.userLogin())
- .prop("deadLine", isoDate(deadLine))
- .prop("fDeadLine", formatDate(deadLine))
- .prop("createdAt", isoDate(actionPlan.createdAt()))
- .prop("fCreatedAt", formatDate(actionPlan.createdAt()))
- .prop("updatedAt", isoDate(actionPlan.updatedAt()))
- .prop("fUpdatedAt", formatDate(updatedAt))
- .endObject();
+ private void addMandatoryValuesToFacet(Facets facets, String facetName, @Nullable Iterable<String> mandatoryValues) {
+ Map<String, Long> buckets = facets.get(facetName);
+ if (buckets != null && mandatoryValues != null) {
+ for (String mandatoryValue : mandatoryValues) {
+ if (!buckets.containsKey(mandatoryValue)) {
+ buckets.put(mandatoryValue, 0L);
+ }
}
- json.endArray();
- }
- }
-
- private Map<String, User> getUsersByLogin(List<String> userLogins) {
- Map<String, User> usersByLogin = newHashMap();
- for (User user : userFinder.findByLogins(userLogins)) {
- usersByLogin.put(user.login(), user);
- }
- return usersByLogin;
- }
-
- private Map<String, ActionPlan> getActionPlanByKeys(Collection<String> actionPlanKeys) {
- Map<String, ActionPlan> actionPlans = newHashMap();
- for (ActionPlan actionPlan : actionPlanService.findByKeys(actionPlanKeys)) {
- actionPlans.put(actionPlan.key(), actionPlan);
}
- return actionPlans;
}
- @CheckForNull
- private static String isoDate(@Nullable Date date) {
- if (date != null) {
- return DateUtils.formatDateTime(date);
+ private void collectLoggedInUser(SearchResponseLoader.Collector collector) {
+ if (userSession.isLoggedIn()) {
+ collector.add(SearchAdditionalField.USERS, userSession.getLogin());
}
- return null;
}
- @CheckForNull
- private String formatDate(@Nullable Date date) {
- if (date != null) {
- return i18n.formatDateTime(userSession.locale(), date);
+ private void collectFacets(SearchResponseLoader.Collector collector, Facets facets) {
+ Set<String> facetRules = facets.getBucketKeys(IssueFilterParameters.RULES);
+ if (facetRules != null) {
+ collector.addAll(SearchAdditionalField.RULES, from(facetRules).transform(RuleKeyFunctions.stringToRuleKey()));
}
- return null;
+ collector.addProjectUuids(facets.getBucketKeys(IssueFilterParameters.PROJECT_UUIDS));
+ collector.addComponentUuids(facets.getBucketKeys(IssueFilterParameters.COMPONENT_UUIDS));
+ collector.addComponentUuids(facets.getBucketKeys(IssueFilterParameters.FILE_UUIDS));
+ collector.addComponentUuids(facets.getBucketKeys(IssueFilterParameters.MODULE_UUIDS));
+ collector.addAll(SearchAdditionalField.USERS, facets.getBucketKeys(IssueFilterParameters.ASSIGNEES));
+ collector.addAll(SearchAdditionalField.USERS, facets.getBucketKeys(IssueFilterParameters.REPORTERS));
+ collector.addAll(SearchAdditionalField.ACTION_PLANS, facets.getBucketKeys(IssueFilterParameters.ACTION_PLANS));
}
- protected void addMandatoryFacetValues(SearchResult<IssueDoc> results, String facetName, @Nullable List<String> mandatoryValues) {
- Map<String, Long> buckets = results.getFacets().get(facetName);
- if (buckets != null && mandatoryValues != null) {
- for (String mandatoryValue : mandatoryValues) {
- if (!buckets.containsKey(mandatoryValue)) {
- buckets.put(mandatoryValue, 0L);
- }
- }
- }
+ private void collectRequestParams(SearchResponseLoader.Collector collector, Request request) {
+ collector.addProjectUuids(request.paramAsStrings(IssueFilterParameters.PROJECT_UUIDS));
+ collector.addComponentUuids(request.paramAsStrings(IssueFilterParameters.FILE_UUIDS));
+ collector.addComponentUuids(request.paramAsStrings(IssueFilterParameters.MODULE_UUIDS));
+ collector.addComponentUuids(request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOT_UUIDS));
+ collector.addAll(SearchAdditionalField.USERS, request.paramAsStrings(IssueFilterParameters.ASSIGNEES));
+ collector.addAll(SearchAdditionalField.USERS, request.paramAsStrings(IssueFilterParameters.REPORTERS));
+ collector.addAll(SearchAdditionalField.ACTION_PLANS, request.paramAsStrings(IssueFilterParameters.ACTION_PLANS));
}
- private static void addZeroFacetsForSelectedItems(Request request, String facetName, Set<String> itemsFromFacets, JsonWriter json) {
- List<String> requestParams = request.paramAsStrings(facetName);
- if (requestParams != null) {
- for (String param : requestParams) {
- if (!itemsFromFacets.contains(param) && !IssueQueryService.LOGIN_MYSELF.equals(param)) {
- json.beginObject();
- json.prop("val", param);
- json.prop("count", 0);
- json.endObject();
- }
- }
+ private enum IssueDocToKey implements Function<IssueDoc, String> {
+ INSTANCE;
+ @Override
+ public String apply(IssueDoc input) {
+ return input.key();
}
}
}
}
public static EnumSet<SearchAdditionalField> getFromRequest(Request request) {
- List<String> labels = request.paramAsStrings(Search2Action.ADDITIONAL_FIELDS);
+ List<String> labels = request.paramAsStrings(SearchAction.ADDITIONAL_FIELDS);
if (labels == null) {
return EnumSet.noneOf(SearchAdditionalField.class);
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue.ws;
+
+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.server.issue.IssueService;
+
+public class SetSeverityAction implements IssuesWsAction {
+
+ public static final String ACTION = "set_severity";
+
+ private final IssueService issueService;
+ private final OperationResponseWriter responseWriter;
+
+ public SetSeverityAction(IssueService issueService, OperationResponseWriter responseWriter) {
+ this.issueService = issueService;
+ this.responseWriter = responseWriter;
+ }
+
+ @Override
+ public void define(WebService.NewController controller) {
+ WebService.NewAction action = controller.createAction(ACTION)
+ .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")
+ .setRequired(true)
+ .setExampleValue("5bccd6e8-f525-43a2-8d76-fcb13dde79ef");
+ action.createParam("severity")
+ .setDescription("New severity")
+ .setRequired(true)
+ .setPossibleValues(Severity.ALL);
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws Exception {
+ String key = request.mandatoryParam("issue");
+ issueService.setSeverity(key, request.mandatoryParam("severity"));
+
+ responseWriter.write(key, request, response);
+ }
+}
import org.sonar.server.component.ComponentService;
import org.sonar.server.component.DefaultComponentFinder;
import org.sonar.server.component.DefaultRubyComponentService;
-import org.sonar.server.component.ws.ComponentJsonWriter;
import org.sonar.server.component.ws.ComponentsWs;
import org.sonar.server.component.ws.EventsWs;
import org.sonar.server.component.ws.ResourcesWs;
import org.sonar.server.issue.notification.NewIssuesEmailTemplate;
import org.sonar.server.issue.notification.NewIssuesNotificationDispatcher;
import org.sonar.server.issue.notification.NewIssuesNotificationFactory;
-import org.sonar.server.issue.ws.ComponentTagsAction;
-import org.sonar.server.issue.ws.IssueActionsWriter;
-import org.sonar.server.issue.ws.IssueComponentHelper;
-import org.sonar.server.issue.ws.IssueJsonWriter;
-import org.sonar.server.issue.ws.IssuesWs;
-import org.sonar.server.issue.ws.OperationResponseWriter;
-import org.sonar.server.issue.ws.SearchResponseFormat;
-import org.sonar.server.issue.ws.SearchResponseLoader;
-import org.sonar.server.issue.ws.SetTagsAction;
+import org.sonar.server.issue.ws.IssueWsModule;
import org.sonar.server.language.ws.LanguageWs;
import org.sonar.server.measure.MeasureFilterEngine;
import org.sonar.server.measure.MeasureFilterExecutor;
import org.sonar.server.notification.NotificationService;
import org.sonar.server.notification.email.AlertsEmailTemplate;
import org.sonar.server.notification.email.EmailNotificationChannel;
+import org.sonar.server.permission.PermissionFinder;
import org.sonar.server.permission.PermissionService;
import org.sonar.server.permission.PermissionTemplateService;
-import org.sonar.server.permission.PermissionFinder;
import org.sonar.server.permission.ws.PermissionsWsModule;
import org.sonar.server.platform.BackendCleanup;
import org.sonar.server.platform.SettingsChangeNotifier;
IndexDefinitions.class,
IndexCreator.class,
- // Activity
+ // Activity
ActivityService.class,
ActivityIndexDefinition.class,
ActivityIndexer.class,
ActivityIndex.class,
- // batch
+ // batch
BatchWsModule.class,
- // Dashboard
+ // Dashboard
DashboardsWs.class,
org.sonar.server.dashboard.ws.ShowAction.class,
ProjectDefaultDashboard.class,
ProjectIssueFilterWidget.class,
IssueTagCloudWidget.class,
- // update center
+ // update center
UpdateCenterClient.class,
UpdateCenterMatrixFactory.class,
UpdateCenterWs.class,
- // quality profile
+ // quality profile
XMLProfileParser.class,
XMLProfileSerializer.class,
AnnotationProfileParser.class,
QProfileReset.class,
RubyQProfileActivityService.class,
- // rule
+ // rule
AnnotationRuleParser.class,
XMLRuleParser.class,
DefaultRuleFinder.class,
RepositoriesAction.class,
org.sonar.server.rule.ws.AppAction.class,
- // languages
+ // languages
Languages.class,
LanguageWs.class,
org.sonar.server.language.ws.ListAction.class,
- // activity
+ // activity
ActivitiesWs.class,
org.sonar.server.activity.ws.SearchAction.class,
ActivityMapping.class,
- // measure
+ // measure
MeasureFilterFactory.class,
MeasureFilterExecutor.class,
MeasureFilterEngine.class,
DefaultMetricFinder.class,
TimeMachineWs.class,
- // quality gates
+ // quality gates
QualityGateDao.class,
QualityGateConditionDao.class,
QualityGates.class,
ProjectQgateAssociationDao.class,
QgateProjectFinder.class,
- org.sonar.server.qualitygate.ws.ListAction.class,
+ org.sonar.server.qualitygate.ws.ListAction.class,
org.sonar.server.qualitygate.ws.SearchAction.class,
org.sonar.server.qualitygate.ws.ShowAction.class,
org.sonar.server.qualitygate.ws.CreateAction.class,
org.sonar.server.qualitygate.ws.AppAction.class,
QGatesWs.class,
- // web services
+ // web services
WebServiceEngine.class,
ListingWs.class,
- // localization
+ // localization
L10nWs.class,
- // authentication
+ // authentication
AuthenticationWs.class,
- // users
+ // users
SecurityRealmFactory.class,
DeprecatedUserFinder.class,
NewUserNotifier.class,
CurrentAction.class,
org.sonar.server.user.ws.SearchAction.class,
org.sonar.server.user.ws.GroupsAction.class,
- org.sonar.server.issue.ws.AuthorsAction.class,
FavoritesWs.class,
UserPropertiesWs.class,
UserIndexDefinition.class,
UserIndex.class,
UserUpdater.class,
- // groups
+ // groups
GroupMembershipService.class,
GroupMembershipFinder.class,
UserGroupsModule.class,
- // permissions
+ // permissions
PermissionRepository.class,
PermissionService.class,
PermissionTemplateService.class,
PermissionFinder.class,
PermissionsWsModule.class,
- // components
+ // components
ProjectsWsModule.class,
DefaultComponentFinder.class,
DefaultRubyComponentService.class,
NewAlerts.class,
NewAlerts.newMetadata(),
ComponentCleanerService.class,
- ComponentJsonWriter.class,
- // views
+ // views
ViewIndexDefinition.class,
ViewIndexer.class,
ViewIndex.class,
- // issues
+ // issues
IssueIndexDefinition.class,
IssueIndexer.class,
IssueAuthorizationIndexer.class,
Actions.class,
IssueBulkChangeService.class,
IssueChangelogFormatter.class,
- IssuesWs.class,
- IssueJsonWriter.class,
- IssueComponentHelper.class,
WsResponseCommonFormat.class,
- SearchResponseLoader.class,
- SearchResponseFormat.class,
- OperationResponseWriter.class,
- org.sonar.server.issue.ws.AssignAction.class,
- org.sonar.server.issue.ws.ShowAction.class,
- org.sonar.server.issue.ws.SearchAction.class,
- org.sonar.server.issue.ws.Search2Action.class,
- org.sonar.server.issue.ws.TagsAction.class,
- SetTagsAction.class,
- ComponentTagsAction.class,
+ IssueWsModule.class,
IssueService.class,
- IssueActionsWriter.class,
IssueQueryService.class,
NewIssuesEmailTemplate.class,
MyNewIssuesEmailTemplate.class,
EmailNotificationChannel.class,
AlertsEmailTemplate.class,
- IssueFilterWsModule.class,
+ IssueFilterWsModule.class,
- // action plan
+ // action plan
ActionPlanWs.class,
ActionPlanService.class,
- // issues actions
+ // issues actions
AssignAction.class,
PlanAction.class,
SetSeverityAction.class,
AddTagsAction.class,
RemoveTagsAction.class,
- // technical debt
+ // technical debt
DebtModelService.class,
DebtModelOperations.class,
DebtModelLookup.class,
DebtRulesXMLImporter.class,
DebtCharacteristicsXMLImporter.class,
- // source
+ // source
HtmlSourceDecorator.class,
SourceService.class,
SourcesWs.class,
SourceLineIndex.class,
SourceLineIndexer.class,
- // Duplications
+ // Duplications
DuplicationsParser.class,
DuplicationsWs.class,
DuplicationsJsonWriter.class,
org.sonar.server.duplication.ws.ShowAction.class,
- // text
+ // text
MacroInterpreter.class,
RubyTextService.class,
- // Notifications
+ // Notifications
EmailSettings.class,
NotificationService.class,
NotificationCenter.class,
DefaultNotificationManager.class,
- // Tests
+ // Tests
CoverageService.class,
TestsWs.class,
CoveredFilesAction.class,
TestIndex.class,
TestIndexer.class,
- // Properties
+ // Properties
PropertiesWs.class,
- TypeValidationModule.class,
+ TypeValidationModule.class,
- // System
+ // System
RestartAction.class,
InfoAction.class,
UpgradesAction.class,
MigrateDbAction.class,
DbMigrationStatusAction.class,
- // Plugins WS
+ // Plugins WS
PluginWSCommons.class,
PluginUpdateAggregator.class,
InstalledAction.class,
CancelAllAction.class,
PluginsWs.class,
- // Compute engine
+ // Compute engine
CEQueueStatusImpl.class,
ComputeEngineQueueMonitor.class,
ReportQueue.class,
ProjectSettingsFactory.class,
IndexPurgeListener.class,
- // UI
+ // UI
GlobalNavigationAction.class,
SettingsNavigationAction.class,
ComponentNavigationAction.class,
import org.mockito.ArgumentCaptor;
import org.sonar.api.issue.ActionPlan;
import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.action.Action;
import org.sonar.api.user.User;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.DefaultActionPlan;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.FieldDiffs;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
import org.sonar.db.component.ResourceDao;
import org.sonar.db.component.ResourceDto;
import org.sonar.db.component.ResourceQuery;
import org.sonar.db.issue.IssueFilterDto;
-import org.sonar.server.component.ws.ComponentJsonWriter;
import org.sonar.server.es.SearchOptions;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.Message;
import org.sonar.server.issue.actionplan.ActionPlanService;
import org.sonar.server.issue.filter.IssueFilterService;
-import org.sonar.server.issue.ws.IssueComponentHelper;
-import org.sonar.server.issue.ws.IssueJsonWriter;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.user.ThreadLocalUserSession;
-import org.sonar.server.user.index.UserIndex;
-import org.sonar.server.user.ws.UserJsonWriter;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
ResourceDao resourceDao;
- ActionService actionService;
-
IssueFilterService issueFilterService;
IssueBulkChangeService issueBulkChangeService;
InternalRubyIssueService service;
- IssueJsonWriter issueWriter;
-
- IssueComponentHelper issueComponentHelper;
-
- UserIndex userIndex;
-
- DbClient dbClient;
-
- DbSession dbSession;
-
- UserJsonWriter userWriter;
-
- ComponentJsonWriter componentWriter;
-
@Before
public void setUp() {
issueService = mock(IssueService.class);
changelogService = mock(IssueChangelogService.class);
actionPlanService = mock(ActionPlanService.class);
resourceDao = mock(ResourceDao.class);
- actionService = mock(ActionService.class);
issueFilterService = mock(IssueFilterService.class);
issueBulkChangeService = mock(IssueBulkChangeService.class);
- issueWriter = mock(IssueJsonWriter.class);
- issueComponentHelper = mock(IssueComponentHelper.class);
- userIndex = mock(UserIndex.class);
- dbClient = mock(DbClient.class);
- dbSession = mock(DbSession.class);
- userWriter = mock(UserJsonWriter.class);
- userWriter = mock(UserJsonWriter.class);
ResourceDto project = new ResourceDto().setKey("org.sonar.Sample");
when(resourceDao.selectResource(any(ResourceQuery.class))).thenReturn(project);
- service = new InternalRubyIssueService(issueService, issueQueryService, commentService, changelogService, actionPlanService, resourceDao, actionService,
- issueFilterService, issueBulkChangeService, issueWriter, issueComponentHelper, componentWriter, userIndex, dbClient, userSessionRule, userWriter);
+ service = new InternalRubyIssueService(issueService, issueQueryService, commentService, changelogService, actionPlanService, resourceDao,
+ issueFilterService, issueBulkChangeService, userSessionRule);
}
@Test
verify(commentService).findComments(newArrayList("ABCD"));
}
- @Test
- public void do_transition() {
- service.doTransition("ABCD", Issue.STATUS_RESOLVED);
- verify(issueService).doTransition(eq("ABCD"), eq(Issue.STATUS_RESOLVED));
- }
-
@Test
public void create_action_plan() {
Map<String, String> parameters = newHashMap();
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue.ws;
+
+import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.core.issue.DefaultIssue;
+import org.sonar.server.issue.IssueService;
+import org.sonar.server.ws.WsAction;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class CreateActionTest {
+
+ IssueService issueService = mock(IssueService.class);
+ OperationResponseWriter responseWriter = mock(OperationResponseWriter.class);
+ WsAction underTest = new CreateAction(issueService, responseWriter);
+ WsActionTester tester = new WsActionTester(underTest);
+
+ @Test
+ public void create_manual_issue_with_default_values() throws Exception {
+ RuleKey ruleKey = RuleKey.of(RuleKey.MANUAL_REPOSITORY_KEY, "S1");
+ when(issueService.createManualIssue("FILE_KEY", ruleKey, null, null, null, null))
+ .thenReturn(new DefaultIssue().setKey("ISSUE_KEY"));
+
+ tester.newRequest()
+ .setParam("component", "FILE_KEY")
+ .setParam("rule", ruleKey.toString())
+ .execute();
+
+ verify(issueService).createManualIssue("FILE_KEY", ruleKey, null, null, null, null);
+ verify(responseWriter).write(eq("ISSUE_KEY"), any(Request.class), any(Response.class));
+ }
+
+ @Test
+ public void create_manual_issue() throws Exception {
+ RuleKey ruleKey = RuleKey.of(RuleKey.MANUAL_REPOSITORY_KEY, "S1");
+ when(issueService.createManualIssue("FILE_KEY", ruleKey, 13, "the msg", "BLOCKER", null))
+ .thenReturn(new DefaultIssue().setKey("ISSUE_KEY"));
+
+ tester.newRequest()
+ .setParam("component", "FILE_KEY")
+ .setParam("rule", ruleKey.toString())
+ .setParam("severity", "BLOCKER")
+ .setParam("line", "13")
+ .setParam("message", "the msg")
+ .execute();
+
+ verify(issueService).createManualIssue("FILE_KEY", ruleKey, 13, "the msg", "BLOCKER", null);
+ verify(responseWriter).write(eq("ISSUE_KEY"), any(Request.class), any(Response.class));
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue.ws;
+
+import org.junit.Test;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.server.issue.IssueService;
+import org.sonar.server.ws.WsAction;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class DoTransitionActionTest {
+
+ IssueService issueService = mock(IssueService.class);
+ OperationResponseWriter responseWriter = mock(OperationResponseWriter.class);
+ WsAction underTest = new DoTransitionAction(issueService, responseWriter);
+ WsActionTester tester = new WsActionTester(underTest);
+
+ @Test
+ public void do_transition() throws Exception {
+ tester.newRequest()
+ .setParam("issue", "ABC")
+ .setParam("transition", "confirm")
+ .execute();
+
+ verify(issueService).doTransition("ABC", "confirm");
+ verify(responseWriter).write(eq("ABC"), any(Request.class), any(Response.class));
+ }
+
+}
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.workflow.Transition;
-import org.sonar.server.issue.ActionService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.test.JsonAssert;
@Mock
IssueService issueService;
- @Mock
- ActionService actionService;
-
IssueActionsWriter writer;
@Before
public void setUp() {
- writer = new IssueActionsWriter(issueService, actionService, userSessionRule);
+ writer = new IssueActionsWriter(issueService, userSessionRule);
}
@Test
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue.ws;
+
+import org.junit.Test;
+import org.sonar.core.platform.ComponentContainer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class IssueWsModuleTest {
+ @Test
+ public void verify_count_of_added_components() {
+ ComponentContainer container = new ComponentContainer();
+ new IssueWsModule().configure(container);
+ assertThat(container.size()).isEqualTo(18);
+ }
+}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue.ws;
+
+import org.junit.Test;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.server.issue.IssueService;
+import org.sonar.server.ws.WsAction;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class PlanActionTest {
+
+ IssueService issueService = mock(IssueService.class);
+ OperationResponseWriter responseWriter = mock(OperationResponseWriter.class);
+ WsAction underTest = new PlanAction(issueService, responseWriter);
+ WsActionTester tester = new WsActionTester(underTest);
+
+ @Test
+ public void plan() throws Exception {
+ tester.newRequest()
+ .setParam("issue", "ABC")
+ .setParam("plan", "P1")
+ .execute();
+
+ verify(issueService).plan("ABC", "P1");
+ verify(responseWriter).write(eq("ABC"), any(Request.class), any(Response.class));
+ }
+
+ @Test
+ public void unplan_if_value_is_absent() throws Exception {
+ tester.newRequest()
+ .setParam("issue", "ABC")
+ .execute();
+
+ verify(issueService).plan("ABC", null);
+ verify(responseWriter).write(eq("ABC"), any(Request.class), any(Response.class));
+ }
+}
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION).execute();
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
result.assertJson(this.getClass(), "issues_on_different_projects.json");
}
session.commit();
tester.get(IssueIndexer.class).indexAll();
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.PROJECT_UUIDS, project.uuid())
.execute()
.assertJson(this.getClass(), "search_by_project_uuid.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.PROJECT_UUIDS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, project.uuid())
.execute()
.assertJson(this.getClass(), "search_by_project_uuid.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");
session.commit();
tester.get(IssueIndexer.class).indexAll();
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.PROJECT_UUIDS, project1.uuid())
.setParam(WebService.Param.FACETS, "projectUuids")
.execute()
session.commit();
tester.get(IssueIndexer.class).indexAll();
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.FILE_UUIDS, file.uuid())
.execute()
.assertJson(this.getClass(), "search_by_file_uuid.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.FILE_UUIDS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, file.uuid())
.execute()
.assertJson(this.getClass(), "search_by_file_uuid.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");
session.commit();
tester.get(IssueIndexer.class).indexAll();
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENTS, file.key())
.execute()
.assertJson(this.getClass(), "search_by_file_key.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENTS, unitTest.key())
.execute()
.assertJson(this.getClass(), "search_by_test_key.json");
session.commit();
tester.get(IssueIndexer.class).indexAll();
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, project.uuid())
.setParam(IssueFilterParameters.FILE_UUIDS, file1.uuid() + "," + file3.uuid())
.setParam(WebService.Param.FACETS, "fileUuids")
session.commit();
tester.get(IssueIndexer.class).indexAll();
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, directory.uuid())
.execute()
.assertJson(this.getClass(), "search_by_file_uuid.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir")
.execute()
.assertJson(this.getClass(), "search_by_file_uuid.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java")
.execute()
.assertJson(this.getClass(), "no_issue.json");
tester.get(IssueIndexer.class).indexAll();
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, directory1.uuid())
.execute()
.assertJson(this.getClass(), "search_by_directory_uuid.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, directory2.uuid())
.execute()
.assertJson(this.getClass(), "no_issue.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.MODULE_UUIDS, module1.uuid())
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir")
.execute()
.assertJson(this.getClass(), "search_by_directory_uuid.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.MODULE_UUIDS, module2.uuid())
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir")
.execute()
.assertJson(this.getClass(), "no_issue.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java/dir")
.execute()
.assertJson(this.getClass(), "search_by_directory_uuid.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.DIRECTORIES, "src/main/java")
.execute()
.assertJson(this.getClass(), "no_issue.json");
session.commit();
tester.get(IssueIndexer.class).indexAll();
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, module.uuid())
.setParam(IssueFilterParameters.MODULE_UUIDS, subModule1.uuid() + "," + subModule3.uuid())
.setParam(WebService.Param.FACETS, "moduleUuids")
tester.get(IssueIndexer.class).indexAll();
userSessionRule.login("john");
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("resolved", "false")
.setParam(WebService.Param.FACETS, "directories")
.execute();
setAnyoneProjectPermission(view, UserRole.USER);
userSessionRule.login("john").addProjectUuidPermissions(UserRole.USER, view.uuid());
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, view.uuid())
.execute()
.assertJson(this.getClass(), "search_by_view_uuid.json");
// User has wrong permission on the view, no issue will be returned
userSessionRule.login("john").addProjectUuidPermissions(UserRole.CODEVIEWER, view.uuid());
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, view.uuid())
.execute()
.assertJson(this.getClass(), "no_issue.json");
setAnyoneProjectPermission(view, UserRole.USER);
userSessionRule.login("john").addComponentUuidPermission(UserRole.USER, view.uuid(), subView.uuid());
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, subView.uuid())
.execute()
.assertJson(this.getClass(), "search_by_view_uuid.json");
// User has wrong permission on the view, no issue will be returned
userSessionRule.login("john").addComponentUuidPermission(UserRole.CODEVIEWER, view.uuid(), subView.uuid());
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, subView.uuid())
.execute()
.assertJson(this.getClass(), "no_issue.json");
session.commit();
tester.get(IssueIndexer.class).indexAll();
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.AUTHORS, "leia")
.setParam(WebService.Param.FACETS, "authors")
.execute()
.assertJson(this.getClass(), "search_by_authors.json");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.AUTHORS, "unknown")
.execute()
.assertJson(this.getClass(), "no_issue.json");
session.commit();
tester.get(IssueIndexer.class).indexAll();
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, developer.uuid())
.execute()
.assertJson(this.getClass(), "search_by_developer.json");
session.commit();
tester.get(IssueIndexer.class).indexAll();
- Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, technicalProject.uuid())
.execute();
result
public void define_action() {
WebService.Controller controller = wsTester.controller("api/issues");
- WebService.Action show = controller.action("search2");
+ WebService.Action show = controller.action("search");
assertThat(show).isNotNull();
assertThat(show.handler()).isNotNull();
assertThat(show.since()).isEqualTo("3.6");
@Test
public void empty_search() throws Exception {
- WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION);
+ WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION);
WsTester.Result result = request.execute();
assertThat(result).isNotNull();
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION).execute();
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
result.assertJson(this.getClass(), "response_contains_all_fields_except_additional_fields.json");
}
tester.get(IssueIndexer.class).indexAll();
userSessionRule.login("john");
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("additionalFields", "comments,users")
.execute();
result.assertJson(this.getClass(), "issue_with_comments.json");
tester.get(IssueIndexer.class).indexAll();
userSessionRule.login("john");
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION).setParam(IssueFilterParameters.HIDE_COMMENTS, "true").execute();
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).setParam(IssueFilterParameters.HIDE_COMMENTS, "true").execute();
result.assertJson(this.getClass(), "issue_with_comment_hidden.json");
assertThat(result.outputAsString()).doesNotContain("fabrice");
}
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("additionalFields", "actionPlans")
.execute();
result.assertJson(this.getClass(), "issue_with_action_plan.json");
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.execute();
result.assertJson(this.getClass(), "issue_with_attributes.json");
}
tester.get(IssueIndexer.class).indexAll();
userSessionRule.login("john");
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("additionalFields", "_all").execute();
result.assertJson(this.getClass(), "load_additional_fields.json");
}
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.execute();
result.assertJson(this.getClass(), "issue_on_removed_file.json");
}
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION).execute();
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
assertThat(result.outputAsString()).contains("\"componentId\":" + file.getId() + ",");
}
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION).setParam(IssueFilterParameters.COMPONENTS, file.getKey()).execute();
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).setParam(IssueFilterParameters.COMPONENTS, file.getKey()).execute();
result.assertJson(this.getClass(), "apply_paging_with_one_component.json");
}
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION).setParam(Search2Action.ADDITIONAL_FIELDS, "_all").execute();
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).setParam(SearchAction.ADDITIONAL_FIELDS, "_all").execute();
result.assertJson(this.getClass(), "components_contains_sub_projects.json");
}
tester.get(IssueIndexer.class).indexAll();
userSessionRule.login("john");
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("resolved", "false")
.setParam(WebService.Param.FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,languages,actionPlans")
.execute();
tester.get(IssueIndexer.class).indexAll();
userSessionRule.login("john");
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("resolved", "false")
.setParam(WebService.Param.FACETS, "statuses,severities,resolutions,projectUuids,rules,fileUuids,assignees,languages,actionPlans")
.setParam("facetMode", "debt")
tester.get(IssueIndexer.class).indexAll();
userSessionRule.login("john");
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("resolved", "false")
.setParam("severities", "MAJOR,MINOR")
.setParam("languages", "xoo,polop,palap")
tester.get(IssueIndexer.class).indexAll();
userSessionRule.login("john");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("resolved", "false")
.setParam("assignees", "__me__")
.setParam(WebService.Param.FACETS, "assignees,assigned_to_me")
session.commit();
tester.get(IssueIndexer.class).indexAll();
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("resolved", "false")
.setParam("assignees", "__me__")
.execute()
tester.get(IssueIndexer.class).indexAll();
userSessionRule.login("john-bob.polop");
- wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("resolved", "false")
.setParam("assignees", "alice")
.setParam(WebService.Param.FACETS, "assignees,assigned_to_me")
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION)
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("sort", IssueQuery.SORT_BY_UPDATE_DATE)
.setParam("asc", "false")
.execute();
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION);
+ WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION);
request.setParam(WebService.Param.PAGE, "2");
request.setParam(WebService.Param.PAGE_SIZE, "9");
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION);
+ WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION);
request.setParam(WebService.Param.PAGE, "1");
request.setParam(WebService.Param.PAGE_SIZE, "-1");
session.commit();
tester.get(IssueIndexer.class).indexAll();
- WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION);
+ WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION);
request.setParam(IssueFilterParameters.PAGE_INDEX, "2");
request.setParam(IssueFilterParameters.PAGE_SIZE, "9");
@Test
public void default_page_size_is_100() throws Exception {
- WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, Search2Action.SEARCH_ACTION);
+ WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION);
WsTester.Result result = request.execute();
result.assertJson(this.getClass(), "default_page_size_is_100.json");
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue.ws;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.server.issue.IssueService;
+import org.sonar.server.ws.WsAction;
+import org.sonar.server.ws.WsActionTester;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+public class SetSeverityActionTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ IssueService issueService = mock(IssueService.class);
+ OperationResponseWriter responseWriter = mock(OperationResponseWriter.class);
+ WsAction underTest = new SetSeverityAction(issueService, responseWriter);
+ WsActionTester tester = new WsActionTester(underTest);
+
+ @Test
+ public void set_severity() throws Exception {
+ tester.newRequest()
+ .setParam("issue", "ABC")
+ .setParam("severity", "BLOCKER")
+ .execute();
+
+ verify(issueService).setSeverity("ABC", "BLOCKER");
+ verify(responseWriter).write(eq("ABC"), any(Request.class), any(Response.class));
+ }
+
+ @Test
+ public void fail_if_bad_severity_value() {
+ expectedException.expect(IllegalArgumentException.class);
+
+ tester.newRequest()
+ .setParam("issue", "ABC")
+ .setParam("severity", "WAT")
+ .execute();
+ }
+}
import org.sonar.db.component.ComponentDto;
import org.sonar.server.component.ComponentTesting;
import org.sonar.server.debt.DebtModelService;
-import org.sonar.server.issue.ActionService;
import org.sonar.server.issue.IssueChangelog;
import org.sonar.server.issue.IssueChangelogService;
import org.sonar.server.issue.IssueCommentService;
@Mock
ActionPlanService actionPlanService;
- @Mock
- ActionService actionService;
-
@Mock
UserFinder userFinder;
tester = new WsTester(new IssuesWs(
new ShowAction(
dbClient, issueService, issueChangelogService, commentService,
- new IssueActionsWriter(issueService, actionService, userSessionRule),
- actionPlanService, userFinder, debtModel, ruleService, i18n, durations, userSessionRule)
- ));
+ new IssueActionsWriter(issueService, userSessionRule),
+ actionPlanService, userFinder, debtModel, ruleService, i18n, durations, userSessionRule)));
}
@Test
.setKey("COMMENT-ABCE")
.setMarkdownText("Another comment")
.setUserLogin("arthur")
- .setCreatedAt(date2)
- ));
+ .setCreatedAt(date2)));
when(userFinder.findByLogin("john")).thenReturn(new DefaultUser().setLogin("john").setName("John"));
when(userFinder.findByLogin("arthur")).thenReturn(new DefaultUser().setLogin("arthur").setName("Arthur"));
)
end
- #
- # POST /api/issues/do_transition?issue=<key>&transition=<key>&comment=<optional comment>
- #
- # -- Example
- # curl -X POST -v -u admin:admin 'http://localhost:9000/api/issues/do_transition?issue=9b6f89c0-3347-46f6-a6d1-dd6c761240e0&transition=resolve'
- #
- def do_transition
- verify_post_request
- require_parameters :issue, :transition
-
- result = Internal.issues.doTransition(params[:issue], params[:transition])
- render_result_issue(result)
- end
-
#
# POST /api/issues/add_comment?issue=<key>&text=<text>
#
end
end
-
- #
- # Change the severity of an existing issue
- #
- # POST /api/issues/set_severity?issue=<key>&severity=<severity>
- #
- # -- Example
- # curl -X POST -v -u admin:admin 'http://localhost:9000/api/issues/set_severity?issue=4a2881e7-825e-4140-a154-01f420c43d11&severity=BLOCKER'
- #
- def set_severity
- verify_post_request
- require_parameters :issue, :severity
-
- result = Internal.issues.setSeverity(params[:issue], params[:severity])
- render_result_issue(result)
- end
-
- #
- # Link an existing issue to an action plan or unlink
- #
- # POST /api/issues/plan?issue=<key>&plan=<optional plan>
- # A nil or blank plan removes the action plan.
- #
- # -- Example
- # curl -X POST -v -u admin:admin 'http://localhost:9000/api/issues/plan?issue=4a2881e7-825e-4140-a154-01f420c43d11&plan=6b851f3c-e25c-432c-aee0-0e13a4184ca3'
- #
- def plan
- verify_post_request
- require_parameters :issue
-
- plan = nil
- plan = params[:plan] if params[:plan] && !params[:plan].blank?
- result = Internal.issues.plan(params[:issue], plan)
- render_result_issue(result)
- end
-
- #
- # Create a manual issue.
- #
- # POST /api/issues/create
- #
- # -- Mandatory parameters
- # 'component' is the component key
- # 'rule' is the rule key prefixed with "manual:", for example 'manual:performance'
- #
- # -- Optional parameters
- # 'severity' is in BLOCKER, CRITICAL, ... INFO. Default value is MAJOR.
- # 'line' starts at 1
- # 'message' is the plain-text message
- #
- # -- Example
- # curl -X POST -v -u admin:admin 'http://localhost:9000/api/issues/create?component=commons-io:commons-io:org.apache.commons.io.filefilter.OrFileFilter&rule=manual:performance&line=2&severity=BLOCKER'
- #
- def create
- verify_post_request
-
- issue_result = Internal.issues.create(params)
- render_result_issue(issue_result)
- end
-
#
# GET /api/issues/actions?issue=<key>
#
)
end
-
- #
- # POST /api/issues/do_action?issue=<key>&actionKey=<action key>
- #
- # -- Example
- # curl -X POST -v -u admin:admin 'http://localhost:9000/api/issues/do_action?issue=9b6f89c0-3347-46f6-a6d1-dd6c761240e0&actionKey=link-to-jira'
- #
- def do_action
- verify_post_request
- require_parameters :issue, :actionKey
-
- result = Internal.issues.executeAction(params[:issue], params[:actionKey])
- render_result_issue(result)
- end
-
#
# Execute a bulk change on a list of issues
#
protected
- def render_result_issue(result)
- hash = result_to_hash(result)
- hash[:issue] = Issue.to_hash(result.get) if result.get
-
- respond_to do |format|
- # if the request header "Accept" is "*/*", then the default format is the first one (json)
- format.json { render :json => Internal.issues.writeIssueJson(result.get), :status => result.httpStatus }
- format.xml { render :xml => hash.to_xml(:skip_types => true, :root => 'sonar', :status => (result.ok ? 200 : 400)) }
- end
- end
def result_to_hash(result)
hash = {}