From 16c40cca4337be4391bba106fe3ae39fe5c73ab2 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Thu, 18 Jul 2013 09:46:19 +0200 Subject: [PATCH] Do not execute transition if not available --- .../server/issue/IssueBulkChangeService.java | 5 +++-- .../sonar/server/issue/TransitionAction.java | 19 ++++++++++++++++- .../issue/IssueBulkChangeServiceTest.java | 1 + .../server/issue/TransitionActionTest.java | 21 +++++++++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) diff --git a/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java b/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java index ec0558f85a8..7793ad6630d 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/IssueBulkChangeService.java @@ -72,8 +72,9 @@ public class IssueBulkChangeService { if (action == null) { throw new BadRequestException("The action : '"+ actionName + "' is unknown"); } - action.verify(issueBulkChangeQuery.properties(actionName), issues, userSession); - bulkActions.add(action); + if (action.verify(issueBulkChangeQuery.properties(actionName), issues, userSession)) { + bulkActions.add(action); + } } IssueChangeContext issueChangeContext = IssueChangeContext.createUser(new Date(), userSession.login()); diff --git a/sonar-server/src/main/java/org/sonar/server/issue/TransitionAction.java b/sonar-server/src/main/java/org/sonar/server/issue/TransitionAction.java index 16da057468a..57e8498e05c 100644 --- a/sonar-server/src/main/java/org/sonar/server/issue/TransitionAction.java +++ b/sonar-server/src/main/java/org/sonar/server/issue/TransitionAction.java @@ -20,11 +20,14 @@ package org.sonar.server.issue; +import com.google.common.base.Predicate; import com.google.common.base.Strings; +import com.google.common.collect.Iterables; import org.sonar.api.ServerComponent; import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.core.issue.workflow.IssueWorkflow; +import org.sonar.core.issue.workflow.Transition; import org.sonar.server.user.UserSession; import java.util.List; @@ -49,7 +52,21 @@ public class TransitionAction extends Action implements ServerComponent { @Override public boolean execute(Map properties, Context context) { - return workflow.doTransition((DefaultIssue) context.issue(), transition(properties), context.issueChangeContext()); + DefaultIssue issue = (DefaultIssue) context.issue(); + String transition = transition(properties); + if (canExecuteTransition(issue, transition)){ + return workflow.doTransition((DefaultIssue) context.issue(), transition(properties), context.issueChangeContext()); + } + return false; + } + + private boolean canExecuteTransition(Issue issue, final String transition){ + return Iterables.find(workflow.outTransitions(issue), new Predicate() { + @Override + public boolean apply(Transition input) { + return input.key().equals(transition); + } + }, null) != null; } private String transition(Map properties) { diff --git a/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java b/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java index bf81543a54b..4ebb6c998c3 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceTest.java @@ -177,6 +177,7 @@ public class IssueBulkChangeServiceTest { actions.add(action); when(action.key()).thenReturn("assign"); when(action.supports(any(Issue.class))).thenReturn(true); + when(action.verify(anyMap(), anyListOf(Issue.class), any(UserSession.class))).thenReturn(true); doThrow(new RuntimeException("Error")).when(action).execute(anyMap(), any(IssueBulkChangeService.ActionContext.class)); IssueBulkChangeQuery issueBulkChangeQuery = new IssueBulkChangeQuery(properties); diff --git a/sonar-server/src/test/java/org/sonar/server/issue/TransitionActionTest.java b/sonar-server/src/test/java/org/sonar/server/issue/TransitionActionTest.java index 6ff1a129c41..b2b6beab892 100644 --- a/sonar-server/src/test/java/org/sonar/server/issue/TransitionActionTest.java +++ b/sonar-server/src/test/java/org/sonar/server/issue/TransitionActionTest.java @@ -27,10 +27,12 @@ import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.issue.internal.IssueChangeContext; import org.sonar.core.issue.workflow.IssueWorkflow; +import org.sonar.core.issue.workflow.Transition; import org.sonar.server.user.MockUserSession; import java.util.Map; +import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Maps.newHashMap; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; @@ -59,10 +61,29 @@ public class TransitionActionTest { Action.Context context = mock(Action.Context.class); when(context.issue()).thenReturn(issue); + when(workflow.outTransitions(context.issue())).thenReturn(newArrayList(Transition.create(transition, "REOPEN", "CONFIRMED"))); + action.execute(properties, context); verify(workflow).doTransition(eq(issue), eq(transition), any(IssueChangeContext.class)); } + @Test + public void should_not_execute_if_transition_is_not_available() { + String transition = "reopen"; + Map properties = newHashMap(); + properties.put("transition", transition); + DefaultIssue issue = mock(DefaultIssue.class); + + Action.Context context = mock(Action.Context.class); + when(context.issue()).thenReturn(issue); + + // Do not contain reopen, transition is not possible + when(workflow.outTransitions(context.issue())).thenReturn(newArrayList(Transition.create("resolve", "OPEN", "RESOLVED"))); + + assertThat(action.execute(properties, context)).isFalse(); + verify(workflow, never()).doTransition(eq(issue), eq(transition), any(IssueChangeContext.class)); + } + @Test public void should_verify_fail_if_parameter_not_found() { String transition = "reopen"; -- 2.39.5