aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2014-09-17 11:24:27 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2014-09-17 11:24:27 +0200
commitafaa0ecdd013e75d9ffb67bfceba8335f16ba6c4 (patch)
tree4e148fe248de77d43f6431426c1c576cf5077d77
parentb1d2bf53909ae35f0f2c36fbaca44a30d9e6c7b5 (diff)
downloadsonarqube-afaa0ecdd013e75d9ffb67bfceba8335f16ba6c4.tar.gz
sonarqube-afaa0ecdd013e75d9ffb67bfceba8335f16ba6c4.zip
SONAR-5531 Provide an implementation based on ES of all "issues relating" web services
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueService.java339
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java14
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java312
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/OldIssueService.java301
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueActionsWriter.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java17
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java162
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java13
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueServiceMediumTest.java391
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyDefaultIssueServiceTest.java (renamed from server/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java)24
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java165
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/OldDefaultIssueServiceTest.java (renamed from server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java)62
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/PublicRubyDefaultIssueServiceTest.java (renamed from server/sonar-server/src/test/java/org/sonar/server/issue/PublicRubyIssueServiceTest.java)2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueDaoTest.java112
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueAuthorizationIndexMediumTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueActionsWriterTest.java25
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueSearchActionTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java3
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java1
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/search/IndexSynchronizerMediumTest.java6
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/get_by_key.xml28
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/insert-result.xml28
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/some_issues.xml (renamed from server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/should_select_all.xml)0
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/update-result.xml28
-rw-r--r--server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/update.xml28
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/IssueNotifications.java11
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java14
-rw-r--r--sonar-core/src/main/java/org/sonar/core/permission/PermissionFacade.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQueryResult.java2
32 files changed, 1409 insertions, 709 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueService.java
new file mode 100644
index 00000000000..c19387a2a42
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/DefaultIssueService.java
@@ -0,0 +1,339 @@
+/*
+ * 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;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.issue.ActionPlan;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.issue.IssueQuery;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.issue.internal.IssueChangeContext;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.user.User;
+import org.sonar.api.user.UserFinder;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.issue.DefaultIssueBuilder;
+import org.sonar.core.issue.IssueNotifications;
+import org.sonar.core.issue.IssueUpdater;
+import org.sonar.core.issue.db.IssueDao;
+import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.issue.db.IssueStorage;
+import org.sonar.core.issue.workflow.IssueWorkflow;
+import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.preview.PreviewCache;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.issue.actionplan.ActionPlanService;
+import org.sonar.server.issue.index.IssueIndex;
+import org.sonar.server.search.IndexClient;
+import org.sonar.server.search.QueryContext;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+public class DefaultIssueService implements IssueService {
+
+ private final DbClient dbClient;
+ private final IndexClient indexClient;
+
+ private final IssueWorkflow workflow;
+ private final IssueUpdater issueUpdater;
+ private final IssueStorage issueStorage;
+ private final IssueNotifications issueNotifications;
+ private final ActionPlanService actionPlanService;
+ private final RuleFinder ruleFinder;
+ private final IssueDao issueDao;
+ private final UserFinder userFinder;
+ private final PreviewCache dryRunCache;
+
+ public DefaultIssueService(DbClient dbClient, IndexClient indexClient,
+ IssueWorkflow workflow,
+ IssueStorage issueStorage,
+ IssueUpdater issueUpdater,
+ IssueNotifications issueNotifications,
+ ActionPlanService actionPlanService,
+ RuleFinder ruleFinder,
+ IssueDao issueDao,
+ UserFinder userFinder,
+ PreviewCache dryRunCache) {
+ this.dbClient = dbClient;
+ this.indexClient = indexClient;
+ this.workflow = workflow;
+ this.issueStorage = issueStorage;
+ this.issueUpdater = issueUpdater;
+ this.actionPlanService = actionPlanService;
+ this.ruleFinder = ruleFinder;
+ this.issueNotifications = issueNotifications;
+ this.issueDao = issueDao;
+ this.userFinder = userFinder;
+ this.dryRunCache = dryRunCache;
+ }
+
+ @Override
+ public List<String> listStatus() {
+ return workflow.statusKeys();
+ }
+
+ /**
+ * List of available transitions.
+ * <p/>
+ * Never return null, but return an empty list if the issue does not exist.
+ */
+ @Override
+ public List<Transition> listTransitions(String issueKey) {
+ DbSession session = dbClient.openSession(false);
+ try {
+ IssueDto issueDto = getByKey(session, issueKey);
+ return listTransitions(issueDto.toDefaultIssue());
+ } finally {
+ session.close();
+ }
+ }
+
+ /**
+ * Never return null, but an empty list if the issue does not exist.
+ * No security check is done since it should already have been done to get the issue
+ */
+ @Override
+ public List<Transition> listTransitions(@Nullable Issue issue) {
+ if (issue == null) {
+ return Collections.emptyList();
+ }
+ List<Transition> outTransitions = workflow.outTransitions(issue);
+ List<Transition> allowedTransitions = new ArrayList<Transition>();
+ for (Transition transition : outTransitions) {
+ DefaultIssue defaultIssue = (DefaultIssue) issue;
+ String projectKey = defaultIssue.projectKey();
+ if (StringUtils.isBlank(transition.requiredProjectPermission()) ||
+ (projectKey != null && UserSession.get().hasProjectPermission(transition.requiredProjectPermission(), projectKey))) {
+ allowedTransitions.add(transition);
+ }
+ }
+ return allowedTransitions;
+ }
+
+ @Override
+ public Issue doTransition(String issueKey, String transitionKey) {
+ verifyLoggedIn();
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ IssueDto issueDto = getByKey(session, issueKey);
+ DefaultIssue defaultIssue = issueDto.toDefaultIssue();
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ checkTransitionPermission(transitionKey, UserSession.get(), defaultIssue);
+ if (workflow.doTransition(defaultIssue, transitionKey, context)) {
+ saveIssue(session, defaultIssue, context);
+ }
+ return defaultIssue;
+
+ } finally {
+ session.close();
+ }
+ }
+
+ private void checkTransitionPermission(String transitionKey, UserSession userSession, DefaultIssue defaultIssue) {
+ List<Transition> outTransitions = workflow.outTransitions(defaultIssue);
+ for (Transition transition : outTransitions) {
+ String projectKey = defaultIssue.projectKey();
+ if (transition.key().equals(transitionKey) && StringUtils.isNotBlank(transition.requiredProjectPermission()) && projectKey != null) {
+ userSession.checkProjectPermission(transition.requiredProjectPermission(), projectKey);
+ }
+ }
+ }
+
+ @Override
+ public Issue assign(String issueKey, @Nullable String assignee) {
+ verifyLoggedIn();
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ IssueDto issueDto = getByKey(session, issueKey);
+ DefaultIssue issue = issueDto.toDefaultIssue();
+ User user = null;
+ if (!Strings.isNullOrEmpty(assignee)) {
+ user = userFinder.findByLogin(assignee);
+ if (user == null) {
+ throw new NotFoundException("Unknown user: " + assignee);
+ }
+ }
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.assign(issue, user, context)) {
+ saveIssue(session, issue, context);
+ }
+ return issue;
+
+ } finally {
+ session.close();
+ }
+ }
+
+ @Override
+ public Issue plan(String issueKey, @Nullable String actionPlanKey) {
+ verifyLoggedIn();
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ ActionPlan actionPlan = null;
+ if (!Strings.isNullOrEmpty(actionPlanKey)) {
+ actionPlan = actionPlanService.findByKey(actionPlanKey, UserSession.get());
+ if (actionPlan == null) {
+ throw new NotFoundException("Unknown action plan: " + actionPlanKey);
+ }
+ }
+ IssueDto issueDto = getByKey(session, issueKey);
+ DefaultIssue issue = issueDto.toDefaultIssue();
+
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.plan(issue, actionPlan, context)) {
+ saveIssue(session, issue, context);
+ }
+ return issue;
+
+ } finally {
+ session.close();
+ }
+ }
+
+ @Override
+ public Issue setSeverity(String issueKey, String severity) {
+ verifyLoggedIn();
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ IssueDto issueDto = getByKey(session, issueKey);
+ DefaultIssue issue = issueDto.toDefaultIssue();
+ UserSession.get().checkProjectPermission(UserRole.ISSUE_ADMIN, issue.projectKey());
+
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.setManualSeverity(issue, severity, context)) {
+ saveIssue(session, issue, context);
+ }
+ return issue;
+ } finally {
+ session.close();
+ }
+ }
+
+ @Override
+ public DefaultIssue createManualIssue(String componentKey, RuleKey ruleKey, @Nullable Integer line, @Nullable String message, @Nullable String severity,
+ @Nullable Double effortToFix) {
+ verifyLoggedIn();
+
+ DbSession session = dbClient.openSession(false);
+ try {
+ ComponentDto component = dbClient.componentDao().getByKey(session, componentKey);
+ ComponentDto project = dbClient.componentDao().getRootProjectByKey(componentKey, session);
+
+ UserSession.get().checkProjectPermission(UserRole.USER, project.getKey());
+ if (!ruleKey.isManual()) {
+ throw new IllegalArgumentException("Issues can be created only on rules marked as 'manual': " + ruleKey);
+ }
+ Rule rule = getRuleByKey(ruleKey);
+
+ DefaultIssue issue = new DefaultIssueBuilder()
+ .componentKey(component.getKey())
+ .projectKey(project.getKey())
+ .line(line)
+ .message(!Strings.isNullOrEmpty(message) ? message : rule.getName())
+ .severity(Objects.firstNonNull(severity, Severity.MAJOR))
+ .effortToFix(effortToFix)
+ .ruleKey(ruleKey)
+ .reporter(UserSession.get().login())
+ .build();
+
+ Date now = new Date();
+ issue.setCreationDate(now);
+ issue.setUpdateDate(now);
+ issueStorage.save(issue);
+ dryRunCache.reportResourceModification(component.getKey());
+ return issue;
+ } finally {
+ session.close();
+ }
+ }
+
+ // TODO result should be replaced by an aggregation object in IssueIndex
+ @Override
+ public RulesAggregation findRulesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
+ RulesAggregation rulesAggregation = new RulesAggregation();
+ for (RuleDto ruleDto : issueDao.findRulesByComponent(componentKey, periodDate, session)) {
+ rulesAggregation.add(ruleDto);
+ }
+ return rulesAggregation;
+ }
+
+ // TODO result should be replaced by an aggregation object in IssueIndex
+ @Override
+ public Multiset<String> findSeveritiesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
+ Multiset<String> aggregation = HashMultiset.create();
+ for (String severity : issueDao.findSeveritiesByComponent(componentKey, periodDate, session)) {
+ aggregation.add(severity);
+ }
+ return aggregation;
+ }
+
+ public IssueDto getByKey(DbSession session, String key) {
+ // Load with index to check permission
+ indexClient.get(IssueIndex.class).getByKey(key);
+ return dbClient.issueDao().getByKey(session, key);
+ }
+
+ private void saveIssue(DbSession session, DefaultIssue issue, IssueChangeContext context) {
+ issueStorage.save(issue);
+ issueNotifications.sendChanges(issue, context,
+ getRuleByKey(issue.ruleKey()),
+ dbClient.componentDao().getByKey(session, issue.projectKey()),
+ dbClient.componentDao().getNullableByKey(session, issue.componentKey()));
+ dryRunCache.reportResourceModification(issue.componentKey());
+ }
+
+ private Rule getRuleByKey(RuleKey ruleKey) {
+ Rule rule = ruleFinder.findByKey(ruleKey);
+ if (rule == null) {
+ throw new IllegalArgumentException("Unknown rule: " + ruleKey);
+ }
+ return rule;
+ }
+
+ public org.sonar.server.search.Result<Issue> search(IssueQuery query, QueryContext options) {
+ IssueIndex issueIndex = indexClient.get(IssueIndex.class);
+ return issueIndex.search(query, options);
+ }
+
+ private void verifyLoggedIn() {
+ UserSession.get().checkLoggedIn();
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
index 1fa162a5dd7..e919ba8f6dc 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/InternalRubyIssueService.java
@@ -110,11 +110,11 @@ public class InternalRubyIssueService implements ServerComponent {
}
public List<Transition> listTransitions(String issueKey) {
- return issueService.listTransitions(issueKey, UserSession.get());
+ return issueService.listTransitions(issueKey);
}
public List<Transition> listTransitions(Issue issue) {
- return issueService.listTransitions(issue, UserSession.get());
+ return issueService.listTransitions(issue);
}
public List<String> listStatus() {
@@ -149,7 +149,7 @@ public class InternalRubyIssueService implements ServerComponent {
public Result<Issue> doTransition(String issueKey, String transitionKey) {
Result<Issue> result = Result.of();
try {
- result.set(issueService.doTransition(issueKey, transitionKey, UserSession.get()));
+ result.set(issueService.doTransition(issueKey, transitionKey));
} catch (Exception e) {
result.addError(e.getMessage());
}
@@ -159,7 +159,7 @@ public class InternalRubyIssueService implements ServerComponent {
public Result<Issue> assign(String issueKey, @Nullable String assignee) {
Result<Issue> result = Result.of();
try {
- result.set(issueService.assign(issueKey, StringUtils.defaultIfBlank(assignee, null), UserSession.get()));
+ result.set(issueService.assign(issueKey, StringUtils.defaultIfBlank(assignee, null)));
} catch (Exception e) {
result.addError(e.getMessage());
}
@@ -169,7 +169,7 @@ public class InternalRubyIssueService implements ServerComponent {
public Result<Issue> setSeverity(String issueKey, String severity) {
Result<Issue> result = Result.of();
try {
- result.set(issueService.setSeverity(issueKey, severity, UserSession.get()));
+ result.set(issueService.setSeverity(issueKey, severity));
} catch (Exception e) {
result.addError(e.getMessage());
}
@@ -179,7 +179,7 @@ public class InternalRubyIssueService implements ServerComponent {
public Result<Issue> plan(String issueKey, @Nullable String actionPlanKey) {
Result<Issue> result = Result.of();
try {
- result.set(issueService.plan(issueKey, actionPlanKey, UserSession.get()));
+ result.set(issueService.plan(issueKey, actionPlanKey));
} catch (Exception e) {
result.addError(e.getMessage());
}
@@ -235,7 +235,7 @@ public class InternalRubyIssueService implements ServerComponent {
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")), UserSession.get());
+ RubyUtils.toDouble(params.get("effortToFix")));
result.set(issue);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java
index 6ef2e3b252f..c60d205fe8a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java
@@ -17,326 +17,44 @@
* 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;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Objects;
-import com.google.common.base.Strings;
-import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.sonar.api.ServerComponent;
-import org.sonar.api.issue.ActionPlan;
import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.IssueQuery;
-import org.sonar.api.issue.IssueQueryResult;
import org.sonar.api.issue.internal.DefaultIssue;
-import org.sonar.api.issue.internal.IssueChangeContext;
import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.Severity;
-import org.sonar.api.rules.Rule;
-import org.sonar.api.rules.RuleFinder;
-import org.sonar.api.user.User;
-import org.sonar.api.user.UserFinder;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.issue.DefaultIssueBuilder;
-import org.sonar.core.issue.IssueNotifications;
-import org.sonar.core.issue.IssueUpdater;
-import org.sonar.core.issue.db.IssueDao;
-import org.sonar.core.issue.db.IssueStorage;
-import org.sonar.core.issue.workflow.IssueWorkflow;
import org.sonar.core.issue.workflow.Transition;
import org.sonar.core.persistence.DbSession;
-import org.sonar.core.preview.PreviewCache;
-import org.sonar.core.resource.ResourceDao;
-import org.sonar.core.resource.ResourceDto;
-import org.sonar.core.resource.ResourceQuery;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.core.user.AuthorizationDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.issue.actionplan.ActionPlanService;
-import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.user.UserSession;
import javax.annotation.Nullable;
-import java.util.*;
-
-/**
- * @since 3.6
- */
-public class IssueService implements ServerComponent {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(IssueService.class);
-
- private final DbClient dbClient;
- private final IndexClient indexClient;
-
- private final DefaultIssueFinder finder;
- private final IssueWorkflow workflow;
- private final IssueUpdater issueUpdater;
- private final IssueStorage issueStorage;
- private final IssueNotifications issueNotifications;
- private final ActionPlanService actionPlanService;
- private final RuleFinder ruleFinder;
- private final ResourceDao resourceDao;
- private final IssueDao issueDao;
- private final AuthorizationDao authorizationDao;
- private final UserFinder userFinder;
- private final PreviewCache dryRunCache;
-
- @Deprecated
- @VisibleForTesting
- public IssueService(DefaultIssueFinder finder,
- IssueWorkflow workflow,
- IssueStorage issueStorage,
- IssueUpdater issueUpdater,
- IssueNotifications issueNotifications,
- ActionPlanService actionPlanService,
- RuleFinder ruleFinder,
- ResourceDao resourceDao,
- IssueDao issueDao,
- AuthorizationDao authorizationDao,
- UserFinder userFinder,
- PreviewCache dryRunCache) {
- this(null, null, finder, workflow, issueStorage, issueUpdater, issueNotifications, actionPlanService,
- ruleFinder, resourceDao, issueDao, authorizationDao, userFinder, dryRunCache);
- }
-
- public IssueService(DbClient dbClient, IndexClient indexClient,
- DefaultIssueFinder finder,
- IssueWorkflow workflow,
- IssueStorage issueStorage,
- IssueUpdater issueUpdater,
- IssueNotifications issueNotifications,
- ActionPlanService actionPlanService,
- RuleFinder ruleFinder,
- ResourceDao resourceDao,
- IssueDao issueDao,
- AuthorizationDao authorizationDao,
- UserFinder userFinder,
- PreviewCache dryRunCache) {
- this.dbClient = dbClient;
- this.indexClient = indexClient;
- this.finder = finder;
- this.workflow = workflow;
- this.issueStorage = issueStorage;
- this.issueUpdater = issueUpdater;
- this.actionPlanService = actionPlanService;
- this.ruleFinder = ruleFinder;
- this.issueNotifications = issueNotifications;
- this.resourceDao = resourceDao;
- this.issueDao = issueDao;
- this.authorizationDao = authorizationDao;
- this.userFinder = userFinder;
- this.dryRunCache = dryRunCache;
- }
-
- /**
- * List of available transitions.
- * <p/>
- * Never return null, but return an empty list if the issue does not exist.
- */
- public List<Transition> listTransitions(String issueKey, UserSession userSession) {
- Issue issue = loadIssue(issueKey).first();
- return listTransitions(issue, userSession);
- }
+import java.util.Date;
+import java.util.List;
- /**
- * Never return null, but an empty list if the issue does not exist.
- * No security check is done since it should already have been done to get the issue
- */
- public List<Transition> listTransitions(@Nullable Issue issue, UserSession userSession) {
- if (issue == null) {
- return Collections.emptyList();
- }
- List<Transition> outTransitions = workflow.outTransitions(issue);
- List<Transition> allowedTransitions = new ArrayList<Transition>();
- for (Transition transition : outTransitions) {
- DefaultIssue defaultIssue = (DefaultIssue) issue;
- String projectKey = defaultIssue.projectKey();
- if (StringUtils.isBlank(transition.requiredProjectPermission()) ||
- (projectKey != null && userSession.hasProjectPermission(transition.requiredProjectPermission(), projectKey))) {
- allowedTransitions.add(transition);
- }
- }
- return allowedTransitions;
- }
+public interface IssueService extends ServerComponent {
+ List<String> listStatus();
- public Issue doTransition(String issueKey, String transitionKey, UserSession userSession) {
- verifyLoggedIn(userSession);
- IssueQueryResult queryResult = loadIssue(issueKey);
- DefaultIssue defaultIssue = (DefaultIssue) queryResult.first();
- IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.login());
- checkTransitionPermission(transitionKey, userSession, defaultIssue);
- if (workflow.doTransition(defaultIssue, transitionKey, context)) {
- issueStorage.save(defaultIssue);
- issueNotifications.sendChanges(defaultIssue, context, queryResult);
- dryRunCache.reportResourceModification(defaultIssue.componentKey());
- }
- return defaultIssue;
- }
+ List<Transition> listTransitions(String issueKey);
- private void checkTransitionPermission(String transitionKey, UserSession userSession, DefaultIssue defaultIssue) {
- List<Transition> outTransitions = workflow.outTransitions(defaultIssue);
- for (Transition transition : outTransitions) {
- String projectKey = defaultIssue.projectKey();
- if (transition.key().equals(transitionKey) && StringUtils.isNotBlank(transition.requiredProjectPermission()) && projectKey != null) {
- userSession.checkProjectPermission(transition.requiredProjectPermission(), projectKey);
- }
- }
- }
+ List<Transition> listTransitions(@Nullable Issue issue);
- public Issue assign(String issueKey, @Nullable String assignee, UserSession userSession) {
- verifyLoggedIn(userSession);
- IssueQueryResult queryResult = loadIssue(issueKey);
- DefaultIssue issue = (DefaultIssue) queryResult.first();
- User user = null;
- if (!Strings.isNullOrEmpty(assignee)) {
- user = userFinder.findByLogin(assignee);
- if (user == null) {
- throw new IllegalArgumentException("Unknown user: " + assignee);
- }
- }
- IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.login());
- if (issueUpdater.assign(issue, user, context)) {
- issueStorage.save(issue);
- issueNotifications.sendChanges(issue, context, queryResult);
- dryRunCache.reportResourceModification(issue.componentKey());
- }
- return issue;
- }
+ Issue doTransition(String issueKey, String transitionKey);
- public Issue plan(String issueKey, @Nullable String actionPlanKey, UserSession userSession) {
- verifyLoggedIn(userSession);
- ActionPlan actionPlan = null;
- if (!Strings.isNullOrEmpty(actionPlanKey)) {
- actionPlan = actionPlanService.findByKey(actionPlanKey, userSession);
- if (actionPlan == null) {
- throw new IllegalArgumentException("Unknown action plan: " + actionPlanKey);
- }
- }
- IssueQueryResult queryResult = loadIssue(issueKey);
- DefaultIssue issue = (DefaultIssue) queryResult.first();
+ Issue assign(String issueKey, @Nullable String assignee);
- IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.login());
- if (issueUpdater.plan(issue, actionPlan, context)) {
- issueStorage.save(issue);
- issueNotifications.sendChanges(issue, context, queryResult);
- dryRunCache.reportResourceModification(issue.componentKey());
- }
- return issue;
- }
+ Issue plan(String issueKey, @Nullable String actionPlanKey);
- public Issue setSeverity(String issueKey, String severity, UserSession userSession) {
- verifyLoggedIn(userSession);
- IssueQueryResult queryResult = loadIssue(issueKey);
- DefaultIssue issue = (DefaultIssue) queryResult.first();
- userSession.checkProjectPermission(UserRole.ISSUE_ADMIN, issue.projectKey());
+ Issue setSeverity(String issueKey, String severity);
- IssueChangeContext context = IssueChangeContext.createUser(new Date(), userSession.login());
- if (issueUpdater.setManualSeverity(issue, severity, context)) {
- issueStorage.save(issue);
- issueNotifications.sendChanges(issue, context, queryResult);
- dryRunCache.reportResourceModification(issue.componentKey());
- }
- return issue;
- }
-
- public DefaultIssue createManualIssue(String componentKey, RuleKey ruleKey, @Nullable Integer line, @Nullable String message, @Nullable String severity,
- @Nullable Double effortToFix, UserSession userSession) {
- verifyLoggedIn(userSession);
- ResourceDto component = resourceDao.getResource(ResourceQuery.create().setKey(componentKey));
- ResourceDto project = resourceDao.getRootProjectByComponentKey(componentKey);
- if (component == null || project == null) {
- throw new IllegalArgumentException("Unknown component: " + componentKey);
- }
- if (!authorizationDao.isAuthorizedComponentKey(component.getKey(), userSession.userId(), UserRole.USER)) {
- // TODO throw unauthorized
- throw new IllegalStateException("User does not have the required role");
- }
- if (!ruleKey.isManual()) {
- throw new IllegalArgumentException("Issues can be created only on rules marked as 'manual': " + ruleKey);
- }
- Rule rule = findRule(ruleKey);
-
- DefaultIssue issue = (DefaultIssue) new DefaultIssueBuilder()
- .componentKey(component.getKey())
- .projectKey(project.getKey())
- .line(line)
- .message(!Strings.isNullOrEmpty(message) ? message : rule.getName())
- .severity(Objects.firstNonNull(severity, Severity.MAJOR))
- .effortToFix(effortToFix)
- .ruleKey(ruleKey)
- .reporter(UserSession.get().login())
- .build();
-
- Date now = new Date();
- issue.setCreationDate(now);
- issue.setUpdateDate(now);
- issueStorage.save(issue);
- dryRunCache.reportResourceModification(component.getKey());
- return issue;
- }
-
- private Rule findRule(RuleKey ruleKey) {
- Rule rule = ruleFinder.findByKey(ruleKey);
- if (rule == null) {
- throw new IllegalArgumentException("Unknown rule: " + ruleKey);
- }
- return rule;
- }
-
- public IssueQueryResult loadIssue(String issueKey) {
- // TODO use IssueIndex for ACL
- // TODO load DTO
- IssueQueryResult result = finder.find(IssueQuery.builder().issueKeys(Arrays.asList(issueKey)).requiredRole(UserRole.USER).build());
- if (result.issues().size() != 1) {
- // TODO throw 404
- throw new IllegalArgumentException("Issue not found: " + issueKey);
- }
- return result;
- }
-
- public List<String> listStatus() {
- return workflow.statusKeys();
- }
-
- private void verifyLoggedIn(UserSession userSession) {
- if (!userSession.isLoggedIn()) {
- // must be logged
- throw new IllegalStateException("User is not logged in");
- }
- }
+ DefaultIssue createManualIssue(String componentKey, RuleKey ruleKey, @Nullable Integer line, @Nullable String message, @Nullable String severity,
+ @Nullable Double effortToFix);
// TODO result should be replaced by an aggregation object in IssueIndex
- public RulesAggregation findRulesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
- RulesAggregation rulesAggregation = new RulesAggregation();
- for (RuleDto ruleDto : issueDao.findRulesByComponent(componentKey, periodDate, session)) {
- rulesAggregation.add(ruleDto);
- }
- return rulesAggregation;
- }
+ RulesAggregation findRulesByComponent(String componentKey, @Nullable Date periodDate, DbSession session);
// TODO result should be replaced by an aggregation object in IssueIndex
- public Multiset<String> findSeveritiesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
- Multiset<String> aggregation = HashMultiset.create();
- for (String severity : issueDao.findSeveritiesByComponent(componentKey, periodDate, session)) {
- aggregation.add(severity);
- }
- return aggregation;
- }
-
- public Issue getByKey(String key) {
- return indexClient.get(IssueIndex.class).getByKey(key);
- }
+ Multiset<String> findSeveritiesByComponent(String componentKey, @Nullable Date periodDate, DbSession session);
- public org.sonar.server.search.Result<Issue> search(IssueQuery query, QueryContext options) {
- IssueIndex issueIndex = indexClient.get(IssueIndex.class);
- return issueIndex.search(query, options);
- }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/OldIssueService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/OldIssueService.java
new file mode 100644
index 00000000000..107ac341c95
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/OldIssueService.java
@@ -0,0 +1,301 @@
+/*
+ * 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;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+import com.google.common.collect.HashMultiset;
+import com.google.common.collect.Multiset;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.issue.ActionPlan;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.issue.IssueQuery;
+import org.sonar.api.issue.IssueQueryResult;
+import org.sonar.api.issue.internal.DefaultIssue;
+import org.sonar.api.issue.internal.IssueChangeContext;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.api.user.User;
+import org.sonar.api.user.UserFinder;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.issue.DefaultIssueBuilder;
+import org.sonar.core.issue.IssueNotifications;
+import org.sonar.core.issue.IssueUpdater;
+import org.sonar.core.issue.db.IssueDao;
+import org.sonar.core.issue.db.IssueStorage;
+import org.sonar.core.issue.workflow.IssueWorkflow;
+import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.preview.PreviewCache;
+import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.resource.ResourceDto;
+import org.sonar.core.resource.ResourceQuery;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.core.user.AuthorizationDao;
+import org.sonar.server.issue.actionplan.ActionPlanService;
+import org.sonar.server.user.UserSession;
+
+import javax.annotation.Nullable;
+
+import java.util.*;
+
+/**
+ * @since 3.6
+ */
+public class OldIssueService implements IssueService {
+
+ private final DefaultIssueFinder finder;
+ private final IssueWorkflow workflow;
+ private final IssueUpdater issueUpdater;
+ private final IssueStorage issueStorage;
+ private final IssueNotifications issueNotifications;
+ private final ActionPlanService actionPlanService;
+ private final RuleFinder ruleFinder;
+ private final ResourceDao resourceDao;
+ private final IssueDao issueDao;
+ private final AuthorizationDao authorizationDao;
+ private final UserFinder userFinder;
+ private final PreviewCache dryRunCache;
+
+ public OldIssueService(
+ DefaultIssueFinder finder,
+ IssueWorkflow workflow,
+ IssueStorage issueStorage,
+ IssueUpdater issueUpdater,
+ IssueNotifications issueNotifications,
+ ActionPlanService actionPlanService,
+ RuleFinder ruleFinder,
+ ResourceDao resourceDao,
+ IssueDao issueDao,
+ AuthorizationDao authorizationDao,
+ UserFinder userFinder,
+ PreviewCache dryRunCache) {
+ this.finder = finder;
+ this.workflow = workflow;
+ this.issueStorage = issueStorage;
+ this.issueUpdater = issueUpdater;
+ this.actionPlanService = actionPlanService;
+ this.ruleFinder = ruleFinder;
+ this.issueNotifications = issueNotifications;
+ this.resourceDao = resourceDao;
+ this.issueDao = issueDao;
+ this.authorizationDao = authorizationDao;
+ this.userFinder = userFinder;
+ this.dryRunCache = dryRunCache;
+ }
+
+ /**
+ * List of available transitions.
+ * <p/>
+ * Never return null, but return an empty list if the issue does not exist.
+ */
+ public List<Transition> listTransitions(String issueKey) {
+ Issue issue = loadIssue(issueKey).first();
+ return listTransitions(issue);
+ }
+
+ /**
+ * Never return null, but an empty list if the issue does not exist.
+ * No security check is done since it should already have been done to get the issue
+ */
+ public List<Transition> listTransitions(@Nullable Issue issue) {
+ if (issue == null) {
+ return Collections.emptyList();
+ }
+ List<Transition> outTransitions = workflow.outTransitions(issue);
+ List<Transition> allowedTransitions = new ArrayList<Transition>();
+ for (Transition transition : outTransitions) {
+ DefaultIssue defaultIssue = (DefaultIssue) issue;
+ String projectKey = defaultIssue.projectKey();
+ if (StringUtils.isBlank(transition.requiredProjectPermission()) ||
+ (projectKey != null && UserSession.get().hasProjectPermission(transition.requiredProjectPermission(), projectKey))) {
+ allowedTransitions.add(transition);
+ }
+ }
+ return allowedTransitions;
+ }
+
+ public Issue doTransition(String issueKey, String transitionKey) {
+ verifyLoggedIn();
+ IssueQueryResult queryResult = loadIssue(issueKey);
+ DefaultIssue defaultIssue = (DefaultIssue) queryResult.first();
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ checkTransitionPermission(transitionKey, UserSession.get(), defaultIssue);
+ if (workflow.doTransition(defaultIssue, transitionKey, context)) {
+ issueStorage.save(defaultIssue);
+ issueNotifications.sendChanges(defaultIssue, context, queryResult);
+ dryRunCache.reportResourceModification(defaultIssue.componentKey());
+ }
+ return defaultIssue;
+ }
+
+ private void checkTransitionPermission(String transitionKey, UserSession userSession, DefaultIssue defaultIssue) {
+ List<Transition> outTransitions = workflow.outTransitions(defaultIssue);
+ for (Transition transition : outTransitions) {
+ String projectKey = defaultIssue.projectKey();
+ if (transition.key().equals(transitionKey) && StringUtils.isNotBlank(transition.requiredProjectPermission()) && projectKey != null) {
+ userSession.checkProjectPermission(transition.requiredProjectPermission(), projectKey);
+ }
+ }
+ }
+
+ public Issue assign(String issueKey, @Nullable String assignee) {
+ verifyLoggedIn();
+ IssueQueryResult queryResult = loadIssue(issueKey);
+ DefaultIssue issue = (DefaultIssue) queryResult.first();
+ User user = null;
+ if (!Strings.isNullOrEmpty(assignee)) {
+ user = userFinder.findByLogin(assignee);
+ if (user == null) {
+ throw new IllegalArgumentException("Unknown user: " + assignee);
+ }
+ }
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.assign(issue, user, context)) {
+ issueStorage.save(issue);
+ issueNotifications.sendChanges(issue, context, queryResult);
+ dryRunCache.reportResourceModification(issue.componentKey());
+ }
+ return issue;
+ }
+
+ public Issue plan(String issueKey, @Nullable String actionPlanKey) {
+ verifyLoggedIn();
+ ActionPlan actionPlan = null;
+ if (!Strings.isNullOrEmpty(actionPlanKey)) {
+ actionPlan = actionPlanService.findByKey(actionPlanKey, UserSession.get());
+ if (actionPlan == null) {
+ throw new IllegalArgumentException("Unknown action plan: " + actionPlanKey);
+ }
+ }
+ IssueQueryResult queryResult = loadIssue(issueKey);
+ DefaultIssue issue = (DefaultIssue) queryResult.first();
+
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.plan(issue, actionPlan, context)) {
+ issueStorage.save(issue);
+ issueNotifications.sendChanges(issue, context, queryResult);
+ dryRunCache.reportResourceModification(issue.componentKey());
+ }
+ return issue;
+ }
+
+ public Issue setSeverity(String issueKey, String severity) {
+ verifyLoggedIn();
+ IssueQueryResult queryResult = loadIssue(issueKey);
+ DefaultIssue issue = (DefaultIssue) queryResult.first();
+ UserSession.get().checkProjectPermission(UserRole.ISSUE_ADMIN, issue.projectKey());
+
+ IssueChangeContext context = IssueChangeContext.createUser(new Date(), UserSession.get().login());
+ if (issueUpdater.setManualSeverity(issue, severity, context)) {
+ issueStorage.save(issue);
+ issueNotifications.sendChanges(issue, context, queryResult);
+ dryRunCache.reportResourceModification(issue.componentKey());
+ }
+ return issue;
+ }
+
+ public DefaultIssue createManualIssue(String componentKey, RuleKey ruleKey, @Nullable Integer line, @Nullable String message, @Nullable String severity,
+ @Nullable Double effortToFix) {
+ verifyLoggedIn();
+ ResourceDto component = resourceDao.getResource(ResourceQuery.create().setKey(componentKey));
+ ResourceDto project = resourceDao.getRootProjectByComponentKey(componentKey);
+ if (component == null || project == null) {
+ throw new IllegalArgumentException("Unknown component: " + componentKey);
+ }
+ if (!authorizationDao.isAuthorizedComponentKey(component.getKey(), UserSession.get().userId(), UserRole.USER)) {
+ // TODO throw unauthorized
+ throw new IllegalStateException("User does not have the required role");
+ }
+ if (!ruleKey.isManual()) {
+ throw new IllegalArgumentException("Issues can be created only on rules marked as 'manual': " + ruleKey);
+ }
+ Rule rule = findRule(ruleKey);
+
+ DefaultIssue issue = (DefaultIssue) new DefaultIssueBuilder()
+ .componentKey(component.getKey())
+ .projectKey(project.getKey())
+ .line(line)
+ .message(!Strings.isNullOrEmpty(message) ? message : rule.getName())
+ .severity(Objects.firstNonNull(severity, Severity.MAJOR))
+ .effortToFix(effortToFix)
+ .ruleKey(ruleKey)
+ .reporter(UserSession.get().login())
+ .build();
+
+ Date now = new Date();
+ issue.setCreationDate(now);
+ issue.setUpdateDate(now);
+ issueStorage.save(issue);
+ dryRunCache.reportResourceModification(component.getKey());
+ return issue;
+ }
+
+ private Rule findRule(RuleKey ruleKey) {
+ Rule rule = ruleFinder.findByKey(ruleKey);
+ if (rule == null) {
+ throw new IllegalArgumentException("Unknown rule: " + ruleKey);
+ }
+ return rule;
+ }
+
+ public IssueQueryResult loadIssue(String issueKey) {
+ // TODO use IssueIndex for ACL
+ // TODO load DTO
+ IssueQueryResult result = finder.find(IssueQuery.builder().issueKeys(Arrays.asList(issueKey)).requiredRole(UserRole.USER).build());
+ if (result.issues().size() != 1) {
+ // TODO throw 404
+ throw new IllegalArgumentException("Issue not found: " + issueKey);
+ }
+ return result;
+ }
+
+ public List<String> listStatus() {
+ return workflow.statusKeys();
+ }
+
+ private void verifyLoggedIn() {
+ if (!UserSession.get().isLoggedIn()) {
+ // must be logged
+ throw new IllegalStateException("User is not logged in");
+ }
+ }
+
+ // TODO result should be replaced by an aggregation object in IssueIndex
+ public RulesAggregation findRulesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
+ RulesAggregation rulesAggregation = new RulesAggregation();
+ for (RuleDto ruleDto : issueDao.findRulesByComponent(componentKey, periodDate, session)) {
+ rulesAggregation.add(ruleDto);
+ }
+ return rulesAggregation;
+ }
+
+ // TODO result should be replaced by an aggregation object in IssueIndex
+ public Multiset<String> findSeveritiesByComponent(String componentKey, @Nullable Date periodDate, DbSession session) {
+ Multiset<String> aggregation = HashMultiset.create();
+ for (String severity : issueDao.findSeveritiesByComponent(componentKey, periodDate, session)) {
+ aggregation.add(severity);
+ }
+ return aggregation;
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueActionsWriter.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueActionsWriter.java
index e4d7cfa04da..4057524f0f8 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueActionsWriter.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueActionsWriter.java
@@ -48,7 +48,7 @@ public class IssueActionsWriter implements ServerComponent {
public void writeTransitions(Issue issue, JsonWriter json) {
json.name("transitions").beginArray();
if (UserSession.get().isLoggedIn()) {
- List<Transition> transitions = issueService.listTransitions(issue, UserSession.get());
+ List<Transition> transitions = issueService.listTransitions(issue);
for (Transition transition : transitions) {
json.value(transition.key());
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
index 20ceda385ea..30fd11a0cc2 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/SearchAction.java
@@ -24,11 +24,7 @@ import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.io.Resources;
import org.sonar.api.i18n.I18n;
-import org.sonar.api.issue.ActionPlan;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.IssueComment;
-import org.sonar.api.issue.IssueQuery;
-import org.sonar.api.issue.IssueQueryResult;
+import org.sonar.api.issue.*;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.api.server.ws.Request;
@@ -45,6 +41,7 @@ import org.sonar.core.persistence.DbSession;
import org.sonar.markdown.Markdown;
import org.sonar.server.component.DefaultComponentFinder;
import org.sonar.server.db.DbClient;
+import org.sonar.server.issue.DefaultIssueService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.issue.actionplan.ActionPlanService;
import org.sonar.server.issue.filter.IssueFilterParameters;
@@ -58,13 +55,7 @@ import org.sonar.server.user.UserSession;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import static com.google.common.collect.Lists.newArrayList;
@@ -229,7 +220,7 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> {
@Override
protected Result<Issue> doSearch(IssueQuery query, QueryContext context) {
- return service.search(query, context);
+ return ((DefaultIssueService)service).search(query, context);
}
@Override
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
index 9ccca614c62..4e4caaae932 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
@@ -51,13 +51,7 @@ import org.sonar.core.measure.db.MeasureFilterDao;
import org.sonar.core.metric.DefaultMetricFinder;
import org.sonar.core.notification.DefaultNotificationManager;
import org.sonar.core.permission.PermissionFacade;
-import org.sonar.core.persistence.DaoUtils;
-import org.sonar.core.persistence.DatabaseVersion;
-import org.sonar.core.persistence.DefaultDatabase;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.persistence.PreviewDatabaseFactory;
-import org.sonar.core.persistence.SemaphoreUpdater;
-import org.sonar.core.persistence.SemaphoresImpl;
+import org.sonar.core.persistence.*;
import org.sonar.core.preview.PreviewCache;
import org.sonar.core.profiling.Profiling;
import org.sonar.core.purge.PurgeProfiler;
@@ -83,57 +77,27 @@ import org.sonar.server.activity.index.ActivityNormalizer;
import org.sonar.server.activity.ws.ActivitiesWebService;
import org.sonar.server.activity.ws.ActivityMapping;
import org.sonar.server.authentication.ws.AuthenticationWs;
-import org.sonar.server.batch.BatchIndex;
-import org.sonar.server.batch.BatchWs;
-import org.sonar.server.batch.GlobalReferentialsAction;
-import org.sonar.server.batch.ProjectReferentialsAction;
-import org.sonar.server.batch.UploadReportAction;
+import org.sonar.server.batch.*;
import org.sonar.server.charts.ChartFactory;
import org.sonar.server.component.ComponentCleanerService;
import org.sonar.server.component.DefaultComponentFinder;
import org.sonar.server.component.DefaultRubyComponentService;
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.component.db.SnapshotDao;
-import org.sonar.server.component.ws.ComponentAppAction;
-import org.sonar.server.component.ws.ComponentsWs;
-import org.sonar.server.component.ws.EventsWs;
-import org.sonar.server.component.ws.ProjectsWs;
-import org.sonar.server.component.ws.ResourcesWs;
+import org.sonar.server.component.ws.*;
import org.sonar.server.config.ws.PropertiesWs;
import org.sonar.server.db.DatabaseChecker;
import org.sonar.server.db.DbClient;
import org.sonar.server.db.EmbeddedDatabaseFactory;
import org.sonar.server.db.migrations.DatabaseMigrations;
import org.sonar.server.db.migrations.DatabaseMigrator;
-import org.sonar.server.debt.DebtCharacteristicsXMLImporter;
-import org.sonar.server.debt.DebtModelBackup;
-import org.sonar.server.debt.DebtModelLookup;
-import org.sonar.server.debt.DebtModelOperations;
-import org.sonar.server.debt.DebtModelPluginRepository;
-import org.sonar.server.debt.DebtModelService;
-import org.sonar.server.debt.DebtModelXMLExporter;
-import org.sonar.server.debt.DebtRulesXMLImporter;
+import org.sonar.server.debt.*;
import org.sonar.server.design.FileDesignWidget;
import org.sonar.server.design.PackageDesignWidget;
import org.sonar.server.duplication.ws.DuplicationsJsonWriter;
import org.sonar.server.duplication.ws.DuplicationsParser;
import org.sonar.server.duplication.ws.DuplicationsWs;
-import org.sonar.server.issue.ActionService;
-import org.sonar.server.issue.AssignAction;
-import org.sonar.server.issue.CommentAction;
-import org.sonar.server.issue.DefaultIssueFinder;
-import org.sonar.server.issue.InternalRubyIssueService;
-import org.sonar.server.issue.IssueBulkChangeService;
-import org.sonar.server.issue.IssueChangelogFormatter;
-import org.sonar.server.issue.IssueChangelogService;
-import org.sonar.server.issue.IssueCommentService;
-import org.sonar.server.issue.IssueService;
-import org.sonar.server.issue.IssueStatsFinder;
-import org.sonar.server.issue.PlanAction;
-import org.sonar.server.issue.PublicRubyIssueService;
-import org.sonar.server.issue.ServerIssueStorage;
-import org.sonar.server.issue.SetSeverityAction;
-import org.sonar.server.issue.TransitionAction;
+import org.sonar.server.issue.*;
import org.sonar.server.issue.actionplan.ActionPlanService;
import org.sonar.server.issue.actionplan.ActionPlanWs;
import org.sonar.server.issue.db.IssueAuthorizationDao;
@@ -167,84 +131,22 @@ import org.sonar.server.platform.ws.L10nWs;
import org.sonar.server.platform.ws.RestartHandler;
import org.sonar.server.platform.ws.ServerWs;
import org.sonar.server.platform.ws.SystemWs;
-import org.sonar.server.plugins.InstalledPluginReferentialFactory;
-import org.sonar.server.plugins.PluginDownloader;
-import org.sonar.server.plugins.ServerExtensionInstaller;
-import org.sonar.server.plugins.ServerPluginJarInstaller;
-import org.sonar.server.plugins.ServerPluginJarsInstaller;
-import org.sonar.server.plugins.ServerPluginRepository;
-import org.sonar.server.plugins.UpdateCenterClient;
-import org.sonar.server.plugins.UpdateCenterMatrixFactory;
+import org.sonar.server.plugins.*;
import org.sonar.server.qualitygate.QgateProjectFinder;
import org.sonar.server.qualitygate.QualityGates;
import org.sonar.server.qualitygate.RegisterQualityGates;
-import org.sonar.server.qualitygate.ws.QGatesAppAction;
-import org.sonar.server.qualitygate.ws.QGatesCopyAction;
-import org.sonar.server.qualitygate.ws.QGatesCreateAction;
-import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesDeselectAction;
-import org.sonar.server.qualitygate.ws.QGatesDestroyAction;
-import org.sonar.server.qualitygate.ws.QGatesListAction;
-import org.sonar.server.qualitygate.ws.QGatesRenameAction;
-import org.sonar.server.qualitygate.ws.QGatesSearchAction;
-import org.sonar.server.qualitygate.ws.QGatesSelectAction;
-import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction;
-import org.sonar.server.qualitygate.ws.QGatesShowAction;
-import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction;
-import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction;
-import org.sonar.server.qualitygate.ws.QGatesWs;
-import org.sonar.server.qualityprofile.BuiltInProfiles;
-import org.sonar.server.qualityprofile.QProfileBackuper;
-import org.sonar.server.qualityprofile.QProfileCopier;
-import org.sonar.server.qualityprofile.QProfileExporters;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.QProfileLoader;
-import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.qualityprofile.QProfileProjectLookup;
-import org.sonar.server.qualityprofile.QProfileProjectOperations;
-import org.sonar.server.qualityprofile.QProfileRepositoryExporter;
-import org.sonar.server.qualityprofile.QProfileReset;
-import org.sonar.server.qualityprofile.QProfileService;
-import org.sonar.server.qualityprofile.QProfiles;
-import org.sonar.server.qualityprofile.RegisterQualityProfiles;
-import org.sonar.server.qualityprofile.RuleActivator;
-import org.sonar.server.qualityprofile.RuleActivatorContextFactory;
+import org.sonar.server.qualitygate.ws.*;
+import org.sonar.server.qualityprofile.*;
import org.sonar.server.qualityprofile.db.ActiveRuleDao;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
-import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions;
-import org.sonar.server.qualityprofile.ws.ProfilesWs;
-import org.sonar.server.qualityprofile.ws.QProfileRestoreBuiltInAction;
-import org.sonar.server.qualityprofile.ws.QProfilesWs;
-import org.sonar.server.qualityprofile.ws.RuleActivationActions;
-import org.sonar.server.rule.DefaultRuleFinder;
-import org.sonar.server.rule.DeprecatedRulesDefinition;
-import org.sonar.server.rule.RegisterRules;
-import org.sonar.server.rule.RubyRuleService;
-import org.sonar.server.rule.RuleCreator;
-import org.sonar.server.rule.RuleDefinitionsLoader;
-import org.sonar.server.rule.RuleDeleter;
-import org.sonar.server.rule.RuleOperations;
-import org.sonar.server.rule.RuleRepositories;
-import org.sonar.server.rule.RuleService;
-import org.sonar.server.rule.RuleUpdater;
+import org.sonar.server.qualityprofile.ws.*;
+import org.sonar.server.rule.*;
import org.sonar.server.rule.db.RuleDao;
import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.rule.index.RuleNormalizer;
-import org.sonar.server.rule.ws.ActiveRuleCompleter;
-import org.sonar.server.rule.ws.AppAction;
-import org.sonar.server.rule.ws.DeleteAction;
-import org.sonar.server.rule.ws.RuleMapping;
-import org.sonar.server.rule.ws.RulesWebService;
-import org.sonar.server.rule.ws.SearchAction;
-import org.sonar.server.rule.ws.TagsAction;
-import org.sonar.server.rule.ws.UpdateAction;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.IndexQueue;
-import org.sonar.server.search.IndexSynchronizer;
-import org.sonar.server.search.SearchClient;
-import org.sonar.server.search.SearchHealth;
+import org.sonar.server.rule.ws.*;
+import org.sonar.server.search.*;
import org.sonar.server.source.CodeColorizers;
import org.sonar.server.source.DeprecatedSourceDecorator;
import org.sonar.server.source.HtmlSourceDecorator;
@@ -253,27 +155,9 @@ import org.sonar.server.source.ws.ScmAction;
import org.sonar.server.source.ws.ScmWriter;
import org.sonar.server.source.ws.ShowAction;
import org.sonar.server.source.ws.SourcesWs;
-import org.sonar.server.startup.CleanPreviewAnalysisCache;
-import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules;
-import org.sonar.server.startup.GeneratePluginIndex;
-import org.sonar.server.startup.GwtPublisher;
-import org.sonar.server.startup.JdbcDriverDeployer;
-import org.sonar.server.startup.LogServerId;
-import org.sonar.server.startup.RegisterDashboards;
-import org.sonar.server.startup.RegisterDebtModel;
-import org.sonar.server.startup.RegisterMetrics;
-import org.sonar.server.startup.RegisterNewMeasureFilters;
-import org.sonar.server.startup.RegisterPermissionTemplates;
-import org.sonar.server.startup.RegisterServletFilters;
-import org.sonar.server.startup.RenameDeprecatedPropertyKeys;
-import org.sonar.server.startup.ServerMetadataPersister;
+import org.sonar.server.startup.*;
import org.sonar.server.test.CoverageService;
-import org.sonar.server.test.ws.CoverageShowAction;
-import org.sonar.server.test.ws.CoverageWs;
-import org.sonar.server.test.ws.TestsCoveredFilesAction;
-import org.sonar.server.test.ws.TestsShowAction;
-import org.sonar.server.test.ws.TestsTestCasesAction;
-import org.sonar.server.test.ws.TestsWs;
+import org.sonar.server.test.ws.*;
import org.sonar.server.text.MacroInterpreter;
import org.sonar.server.text.RubyTextService;
import org.sonar.server.ui.JRubyI18n;
@@ -281,23 +165,12 @@ import org.sonar.server.ui.JRubyProfiling;
import org.sonar.server.ui.PageDecorations;
import org.sonar.server.ui.Views;
import org.sonar.server.updatecenter.ws.UpdateCenterWs;
-import org.sonar.server.user.DefaultUserService;
-import org.sonar.server.user.DoPrivileged;
-import org.sonar.server.user.GroupMembershipFinder;
-import org.sonar.server.user.GroupMembershipService;
-import org.sonar.server.user.NewUserNotifier;
-import org.sonar.server.user.SecurityRealmFactory;
+import org.sonar.server.user.*;
import org.sonar.server.user.db.GroupDao;
import org.sonar.server.user.ws.FavoritesWs;
import org.sonar.server.user.ws.UserPropertiesWs;
import org.sonar.server.user.ws.UsersWs;
-import org.sonar.server.util.BooleanTypeValidation;
-import org.sonar.server.util.FloatTypeValidation;
-import org.sonar.server.util.IntegerTypeValidation;
-import org.sonar.server.util.StringListTypeValidation;
-import org.sonar.server.util.StringTypeValidation;
-import org.sonar.server.util.TextTypeValidation;
-import org.sonar.server.util.TypeValidations;
+import org.sonar.server.util.*;
import org.sonar.server.ws.ListingWs;
import org.sonar.server.ws.WebServiceEngine;
@@ -595,7 +468,6 @@ class ServerComponents {
pico.addSingleton(IssueUpdater.class);
pico.addSingleton(FunctionExecutor.class);
pico.addSingleton(IssueWorkflow.class);
- pico.addSingleton(IssueService.class);
pico.addSingleton(IssueCommentService.class);
pico.addSingleton(DefaultIssueFinder.class);
pico.addSingleton(IssueStatsFinder.class);
@@ -613,8 +485,10 @@ class ServerComponents {
// Switch Issue search
if (properties.getProperty("sonar.issues.use_es_backend", null) != null) {
pico.addSingleton(org.sonar.server.issue.ws.SearchAction.class);
+ pico.addSingleton(DefaultIssueService.class);
} else {
pico.addSingleton(IssueSearchAction.class);
+ pico.addSingleton(OldIssueService.class);
}
pico.addSingleton(IssueActionsWriter.class);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java b/server/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
index 8a847ef35ea..1ffcb84bf46 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/search/IndexSynchronizer.java
@@ -21,6 +21,7 @@ package org.sonar.server.search;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Settings;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.activity.index.ActivityIndex;
import org.sonar.server.db.Dao;
@@ -41,10 +42,12 @@ public class IndexSynchronizer {
private final DbClient db;
private final IndexClient index;
+ private final Settings settings;
- public IndexSynchronizer(DbClient db, IndexClient index) {
+ public IndexSynchronizer(DbClient db, IndexClient index, Settings settings) {
this.db = db;
this.index = index;
+ this.settings = settings;
}
public void execute() {
@@ -53,8 +56,13 @@ public class IndexSynchronizer {
LOG.info("Starting DB to Index synchronization");
long start = System.currentTimeMillis();
synchronize(session, db.ruleDao(), index.get(RuleIndex.class));
- synchronize(session, db.issueDao(), index.get(IssueIndex.class));
- synchronize(session, db.issueAuthorizationDao(), index.get(IssueAuthorizationIndex.class));
+
+ // Switch Issue search
+ if (settings.getString("sonar.issues.use_es_backend") != null) {
+ synchronize(session, db.issueDao(), index.get(IssueIndex.class));
+ synchronize(session, db.issueAuthorizationDao(), index.get(IssueAuthorizationIndex.class));
+ }
+
synchronize(session, db.activeRuleDao(), index.get(ActiveRuleIndex.class));
synchronize(session, db.activityDao(), index.get(ActivityIndex.class));
session.commit();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java
index 5de5a0bac76..34a0835706e 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentAppActionTest.java
@@ -350,7 +350,6 @@ public class ComponentAppActionTest {
MockUserSession.set().addComponentPermission(UserRole.USER, SUB_PROJECT_KEY, COMPONENT_KEY);
addComponent();
-
addMeasure(CoreMetrics.IT_COVERAGE_KEY, 85.2);
WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("key", COMPONENT_KEY);
@@ -365,7 +364,7 @@ public class ComponentAppActionTest {
when(resourceDao.getLastSnapshotByResourceId(eq(1L), eq(session))).thenReturn(
new SnapshotDto().setPeriodMode(1, "previous_analysis").setPeriodDate(1, DateUtils.parseDate("2014-05-08"))
- );
+ );
when(periods.label(anyString(), anyString(), any(Date.class))).thenReturn("since previous analysis (May 08 2014)");
WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("key", COMPONENT_KEY);
@@ -409,7 +408,7 @@ public class ComponentAppActionTest {
addComponent();
when(issueService.findRulesByComponent(COMPONENT_KEY, null, session)).thenReturn(
new RulesAggregation().add(new RuleDto().setRuleKey("AvoidCycle").setRepositoryKey("squid").setName("Avoid Cycle"))
- );
+ );
WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("key", COMPONENT_KEY);
request.execute().assertJson(getClass(), "app_with_rules.json");
@@ -424,12 +423,12 @@ public class ComponentAppActionTest {
Date periodDate = DateUtils.parseDate("2014-05-08");
when(resourceDao.getLastSnapshotByResourceId(eq(1L), eq(session))).thenReturn(
new SnapshotDto().setPeriodMode(1, "previous_analysis").setPeriodDate(1, periodDate)
- );
+ );
when(periods.label(anyString(), anyString(), any(Date.class))).thenReturn("since previous analysis (May 08 2014)");
when(issueService.findRulesByComponent(COMPONENT_KEY, periodDate, session)).thenReturn(
new RulesAggregation().add(new RuleDto().setRuleKey("AvoidCycle").setRepositoryKey("squid").setName("Avoid Cycle"))
- );
+ );
WsTester.TestRequest request = tester.newGetRequest("api/components", "app").setParam("key", COMPONENT_KEY).setParam("period", "1");
request.execute().assertJson(getClass(), "app_with_rules_when_period_is_set.json");
@@ -485,11 +484,11 @@ public class ComponentAppActionTest {
when(componentDao.getById(1L, session)).thenReturn(new ComponentDto().setId(1L).setLongName("SonarQube").setKey("org.codehaus.sonar:sonar"));
}
- private void addPeriod(){
+ private void addPeriod() {
Date periodDate = DateUtils.parseDate("2014-05-08");
when(resourceDao.getLastSnapshotByResourceId(eq(1L), eq(session))).thenReturn(
new SnapshotDto().setPeriodMode(1, "previous_analysis").setPeriodDate(1, periodDate)
- );
+ );
when(periods.label(anyString(), anyString(), any(Date.class))).thenReturn("since previous analysis (May 08 2014)");
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueServiceMediumTest.java
new file mode 100644
index 00000000000..708b5dc80cb
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/DefaultIssueServiceMediumTest.java
@@ -0,0 +1,391 @@
+/*
+ * 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;
+
+import com.google.common.collect.Multiset;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.issue.DefaultTransitions;
+import org.sonar.api.issue.Issue;
+import org.sonar.api.issue.IssueQuery;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.security.DefaultGroups;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.issue.db.ActionPlanDto;
+import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.core.permission.PermissionFacade;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.rule.RuleDto;
+import org.sonar.core.user.UserDto;
+import org.sonar.server.component.SnapshotTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.component.db.SnapshotDao;
+import org.sonar.server.db.DbClient;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.issue.db.IssueDao;
+import org.sonar.server.issue.index.IssueIndex;
+import org.sonar.server.rule.RuleTesting;
+import org.sonar.server.rule.db.RuleDao;
+import org.sonar.server.search.IndexClient;
+import org.sonar.server.search.QueryContext;
+import org.sonar.server.tester.ServerTester;
+import org.sonar.server.user.MockUserSession;
+
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class DefaultIssueServiceMediumTest {
+
+ @ClassRule
+ public static ServerTester tester = new ServerTester()
+ .setProperty("sonar.issues.use_es_backend", "true");
+
+ DbClient db;
+ IndexClient indexClient;
+ DbSession session;
+ IssueService service;
+
+ RuleDto rule;
+ ComponentDto project;
+ ComponentDto file;
+ UserDto connectedUser;
+
+ @Before
+ public void setUp() throws Exception {
+ tester.clearDbAndIndexes();
+ db = tester.get(DbClient.class);
+ indexClient = tester.get(IndexClient.class);
+ session = db.openSession(false);
+ service = tester.get(IssueService.class);
+
+ rule = RuleTesting.newXooX1();
+ tester.get(RuleDao.class).insert(session, rule);
+
+ project = new ComponentDto()
+ .setKey("MyProject")
+ .setLongName("My Project")
+ .setQualifier(Qualifiers.PROJECT)
+ .setScope(Scopes.PROJECT);
+ tester.get(ComponentDao.class).insert(session, project);
+ tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(project));
+
+ file = new ComponentDto()
+ .setProjectId(project.getId())
+ .setSubProjectId(project.getId())
+ .setKey("MyComponent")
+ .setLongName("My Component");
+ tester.get(ComponentDao.class).insert(session, file);
+ tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(file));
+
+ // project can be seen by anyone
+ tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
+ db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
+
+ connectedUser = new UserDto().setLogin("gandalf").setName("Gandalf");
+ db.userDao().insert(session, connectedUser);
+ tester.get(PermissionFacade.class).insertUserPermission(project.getId(), connectedUser.getId(), UserRole.USER, session);
+
+ MockUserSession.set()
+ .setLogin(connectedUser.getLogin())
+ .setUserId(connectedUser.getId().intValue())
+ .setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN)
+ .addProjectPermissions(UserRole.USER, project.key())
+ .addProjectPermissions(UserRole.ISSUE_ADMIN, project.key());
+
+ session.commit();
+ }
+
+ @After
+ public void after() {
+ session.close();
+ }
+
+ @Test
+ public void can_facet() throws Exception {
+ IssueDto issue1 = newIssue().setActionPlanKey("P1");
+ IssueDto issue2 = newIssue().setActionPlanKey("P2").setResolution("NONE");
+ tester.get(IssueDao.class).insert(session, issue1, issue2);
+ session.commit();
+
+ org.sonar.server.search.Result<Issue> result = ((DefaultIssueService) service).search(IssueQuery.builder().build(), new QueryContext());
+ assertThat(result.getHits()).hasSize(2);
+ assertThat(result.getFacets()).isEmpty();
+
+ result = ((DefaultIssueService) service).search(IssueQuery.builder().build(), new QueryContext().setFacet(true));
+ assertThat(result.getFacets().keySet()).hasSize(4);
+ assertThat(result.getFacetKeys("actionPlan")).hasSize(2);
+ }
+
+ @Test
+ public void list_status() {
+ assertThat(service.listStatus()).containsExactly("OPEN", "CONFIRMED", "REOPENED", "RESOLVED", "CLOSED");
+ }
+
+ @Test
+ public void list_transitions() {
+ IssueDto issue = newIssue().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FALSE_POSITIVE);
+ tester.get(IssueDao.class).insert(session, issue);
+ session.commit();
+
+ List<Transition> result = service.listTransitions(issue.getKey());
+ assertThat(result).hasSize(1);
+ assertThat(result.get(0).key()).isEqualTo("reopen");
+ }
+
+ @Test
+ public void do_transition() {
+ IssueDto issue = newIssue().setStatus(Issue.STATUS_OPEN);
+ tester.get(IssueDao.class).insert(session, issue);
+ session.commit();
+
+ assertThat(db.issueDao().getByKey(session, issue.getKey())).isNotNull();
+ IssueTesting.assertIsEquivalent(issue, indexClient.get(IssueIndex.class).getByKey(issue.getKey()));
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).status()).isEqualTo(Issue.STATUS_OPEN);
+
+ service.doTransition(issue.getKey(), DefaultTransitions.CONFIRM);
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).status()).isEqualTo(Issue.STATUS_CONFIRMED);
+ }
+
+ @Test
+ public void assign() {
+ IssueDto issue = newIssue();
+ tester.get(IssueDao.class).insert(session, issue);
+
+ UserDto user = new UserDto().setLogin("perceval").setName("Perceval");
+ db.userDao().insert(session, user);
+ session.commit();
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).assignee()).isNull();
+
+ service.assign(issue.getKey(), user.getLogin());
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).assignee()).isEqualTo("perceval");
+ }
+
+ @Test
+ public void un_assign() {
+ IssueDto issue = newIssue().setAssignee("perceval");
+ tester.get(IssueDao.class).insert(session, issue);
+
+ UserDto user = new UserDto().setLogin("perceval").setName("Perceval");
+ db.userDao().insert(session, user);
+ session.commit();
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).assignee()).isEqualTo("perceval");
+
+ service.assign(issue.getKey(), "");
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).assignee()).isNull();
+ }
+
+ @Test
+ public void fail_to_assign_on_unknown_user() {
+ IssueDto issue = newIssue();
+ tester.get(IssueDao.class).insert(session, issue);
+ session.commit();
+
+ try {
+ service.assign(issue.getKey(), "unknown");
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("Unknown user: unknown");
+ }
+ }
+
+ @Test
+ public void plan() {
+ IssueDto issue = newIssue();
+ tester.get(IssueDao.class).insert(session, issue);
+
+ String actionPlanKey = "EFGH";
+ db.actionPlanDao().save(new ActionPlanDto().setKey(actionPlanKey).setProjectId(project.getId()));
+ session.commit();
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).actionPlanKey()).isNull();
+
+ service.plan(issue.getKey(), actionPlanKey);
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).actionPlanKey()).isEqualTo(actionPlanKey);
+ }
+
+ @Test
+ public void un_plan() {
+ String actionPlanKey = "EFGH";
+ db.actionPlanDao().save(new ActionPlanDto().setKey(actionPlanKey).setProjectId(project.getId()));
+
+ IssueDto issue = newIssue().setActionPlanKey(actionPlanKey);
+ tester.get(IssueDao.class).insert(session, issue);
+ session.commit();
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).actionPlanKey()).isEqualTo(actionPlanKey);
+
+ service.plan(issue.getKey(), null);
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).actionPlanKey()).isNull();
+ }
+
+ @Test
+ public void fail_plan_if_action_plan_not_found() {
+ tester.get(IssueDao.class).insert(session, newIssue());
+ session.commit();
+
+ try {
+ service.plan("ABCD", "unknown");
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(NotFoundException.class).hasMessage("Unknown action plan: unknown");
+ }
+ }
+
+ @Test
+ public void set_severity() {
+ IssueDto issue = newIssue().setSeverity(Severity.BLOCKER);
+ tester.get(IssueDao.class).insert(session, issue);
+ session.commit();
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).severity()).isEqualTo(Severity.BLOCKER);
+
+ service.setSeverity(issue.getKey(), Severity.MINOR);
+
+ assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).severity()).isEqualTo(Severity.MINOR);
+ }
+
+ @Test
+ public void create_manual_issue() {
+ RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey");
+ tester.get(RuleDao.class).insert(session, manualRule);
+ session.commit();
+
+ Issue result = service.createManualIssue(file.key(), manualRule.getKey(), 10, "Fix it", Severity.MINOR, 2d);
+
+ Issue manualIssue = indexClient.get(IssueIndex.class).getByKey(result.key());
+ assertThat(manualIssue.componentKey()).isEqualTo(file.key());
+ assertThat(manualIssue.projectKey()).isEqualTo(project.key());
+ assertThat(manualIssue.ruleKey()).isEqualTo(manualRule.getKey());
+ assertThat(manualIssue.message()).isEqualTo("Fix it");
+ assertThat(manualIssue.line()).isEqualTo(10);
+ assertThat(manualIssue.severity()).isEqualTo(Severity.MINOR);
+ assertThat(manualIssue.effortToFix()).isEqualTo(2d);
+ assertThat(manualIssue.reporter()).isEqualTo(connectedUser.getLogin());
+ }
+
+ @Test
+ public void create_manual_issue_with_major_severity_when_no_severity() {
+ RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey");
+ tester.get(RuleDao.class).insert(session, manualRule);
+ session.commit();
+
+ Issue result = service.createManualIssue(file.key(), manualRule.getKey(), 10, "Fix it", null, 2d);
+
+ Issue manualIssue = indexClient.get(IssueIndex.class).getByKey(result.key());
+ assertThat(manualIssue.severity()).isEqualTo(Severity.MAJOR);
+ }
+
+ @Test
+ public void create_manual_issue_with_rule_name_when_no_message() {
+ RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey").setName("Manual rule name");
+ tester.get(RuleDao.class).insert(session, manualRule);
+ session.commit();
+
+ Issue result = service.createManualIssue(file.key(), manualRule.getKey(), 10, null, null, 2d);
+
+ Issue manualIssue = indexClient.get(IssueIndex.class).getByKey(result.key());
+ assertThat(manualIssue.message()).isEqualTo("Manual rule name");
+ }
+
+ @Test
+ public void fail_create_manual_issue_on_not_manual_rule() {
+ try {
+ service.createManualIssue(file.key(), rule.getKey(), 10, "Fix it", null, 2d);
+ fail();
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Issues can be created only on rules marked as 'manual': xoo:x1");
+ }
+ }
+
+ @Test(expected = ForbiddenException.class)
+ public void fail_create_manual_issue_if_not_having_required_role() {
+ // User has not the 'user' role on the project
+ MockUserSession.set()
+ .setLogin(connectedUser.getLogin())
+ .setUserId(connectedUser.getId().intValue())
+ .setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN)
+ .addProjectPermissions(UserRole.CODEVIEWER, project.key());
+
+ RuleDto manualRule = RuleTesting.newManualRule("manualRuleKey");
+ tester.get(RuleDao.class).insert(session, manualRule);
+ session.commit();
+
+ service.createManualIssue(file.key(), rule.getKey(), 10, "Fix it", null, 2d);
+ }
+
+ @Test
+ public void find_rules_by_component() throws Exception {
+ // 2 issues on the same rule
+ tester.get(IssueDao.class).insert(session, newIssue().setRule(rule));
+ tester.get(IssueDao.class).insert(session, newIssue().setRule(rule));
+ session.commit();
+
+ RulesAggregation result = service.findRulesByComponent(file.key(), null, session);
+ assertThat(result.rules()).hasSize(1);
+ }
+
+ @Test
+ public void find_rules_by_severity() throws Exception {
+ tester.get(IssueDao.class).insert(session, newIssue().setSeverity(Severity.MAJOR));
+ tester.get(IssueDao.class).insert(session, newIssue().setSeverity(Severity.MAJOR));
+ tester.get(IssueDao.class).insert(session, newIssue().setSeverity(Severity.INFO));
+ session.commit();
+
+ Multiset<String> result = service.findSeveritiesByComponent(file.key(), null, session);
+ assertThat(result.count("MAJOR")).isEqualTo(2);
+ assertThat(result.count("INFO")).isEqualTo(1);
+ assertThat(result.count("UNKNOWN")).isEqualTo(0);
+ }
+
+ private IssueDto newIssue() {
+ return new IssueDto()
+ .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
+ .setIssueUpdateDate(DateUtils.parseDate("2014-12-04"))
+ .setRule(rule)
+ .setDebt(10L)
+ .setRootComponent(project)
+ .setComponent(file)
+ .setStatus(Issue.STATUS_OPEN)
+ .setResolution(null)
+ .setSeverity(Severity.MAJOR)
+ .setKee(UUID.randomUUID().toString());
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyDefaultIssueServiceTest.java
index 508890be52b..b807c0bc5f2 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyIssueServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/InternalRubyDefaultIssueServiceTest.java
@@ -59,34 +59,34 @@ import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
-public class InternalRubyIssueServiceTest {
+public class InternalRubyDefaultIssueServiceTest {
@Mock
IssueService issueService;
@Mock
- IssueCommentService commentService = mock(IssueCommentService.class);
+ IssueCommentService commentService;
@Mock
- IssueChangelogService changelogService = mock(IssueChangelogService.class);
+ IssueChangelogService changelogService;
@Mock
- ActionPlanService actionPlanService = mock(ActionPlanService.class);
+ ActionPlanService actionPlanService;
@Mock
- ResourceDao resourceDao = mock(ResourceDao.class);
+ ResourceDao resourceDao;
@Mock
- IssueStatsFinder issueStatsFinder = mock(IssueStatsFinder.class);
+ IssueStatsFinder issueStatsFinder;
@Mock
- ActionService actionService = mock(ActionService.class);
+ ActionService actionService;
@Mock
- IssueFilterService issueFilterService = mock(IssueFilterService.class);
+ IssueFilterService issueFilterService;
@Mock
- IssueBulkChangeService issueBulkChangeService = mock(IssueBulkChangeService.class);
+ IssueBulkChangeService issueBulkChangeService;
InternalRubyIssueService service;
@@ -107,14 +107,14 @@ public class InternalRubyIssueServiceTest {
@Test
public void list_transitions_by_issue_key() throws Exception {
service.listTransitions("ABCD");
- verify(issueService).listTransitions(eq("ABCD"), any(UserSession.class));
+ verify(issueService).listTransitions(eq("ABCD"));
}
@Test
public void list_transitions_by_issue() throws Exception {
Issue issue = new DefaultIssue().setKey("ABCD");
service.listTransitions(issue);
- verify(issueService).listTransitions(eq(issue), any(UserSession.class));
+ verify(issueService).listTransitions(eq(issue));
}
@Test
@@ -141,7 +141,7 @@ public class InternalRubyIssueServiceTest {
@Test
public void do_transition() throws Exception {
service.doTransition("ABCD", Issue.STATUS_RESOLVED);
- verify(issueService).doTransition(eq("ABCD"), eq(Issue.STATUS_RESOLVED), any(UserSession.class));
+ verify(issueService).doTransition(eq("ABCD"), eq(Issue.STATUS_RESOLVED));
}
@Test
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java
deleted file mode 100644
index ac4e5069a02..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.issue.DefaultTransitions;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.issue.IssueQuery;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Scopes;
-import org.sonar.api.rule.Severity;
-import org.sonar.api.security.DefaultGroups;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.issue.db.IssueDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.permission.PermissionFacade;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.core.user.UserDto;
-import org.sonar.server.component.SnapshotTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.component.db.SnapshotDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.issue.db.IssueDao;
-import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.rule.RuleTesting;
-import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.user.MockUserSession;
-import org.sonar.server.user.UserSession;
-
-import java.util.Date;
-import java.util.UUID;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class IssueServiceMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester();
-
- DbClient db;
- IndexClient indexClient;
- DbSession session;
- IssueService service;
- UserSession userSession;
-
- RuleDto rule;
- ComponentDto project;
- ComponentDto resource;
-
- @Before
- public void setUp() throws Exception {
- tester.clearDbAndIndexes();
- db = tester.get(DbClient.class);
- indexClient = tester.get(IndexClient.class);
- session = db.openSession(false);
- service = tester.get(IssueService.class);
-
- rule = RuleTesting.newXooX1();
- tester.get(RuleDao.class).insert(session, rule);
-
- project = new ComponentDto()
- .setKey("MyProject")
- .setLongName("My Project")
- .setQualifier(Qualifiers.PROJECT)
- .setScope(Scopes.PROJECT);
- tester.get(ComponentDao.class).insert(session, project);
- tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(project));
-
- resource = new ComponentDto()
- .setProjectId(project.getId())
- .setKey("MyComponent")
- .setLongName("My Component");
- tester.get(ComponentDao.class).insert(session, resource);
- tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(resource));
-
- // project can be seen by anyone
- tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
- db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
-
- UserDto user = new UserDto().setLogin("gandalf").setName("Gandalf");
- db.userDao().insert(session, user);
- tester.get(PermissionFacade.class).insertUserPermission(project.getId(), user.getId(), UserRole.USER, session);
-
- userSession = MockUserSession.create().setLogin(user.getLogin()).setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN)
- .addProjectPermissions(UserRole.USER, project.key());
-
- session.commit();
- }
-
- @After
- public void after() {
- session.close();
- }
-
- @Test
- public void can_facet() throws Exception {
- IssueDto issue1 = getIssue().setActionPlanKey("P1");
- IssueDto issue2 = getIssue().setActionPlanKey("P2").setResolution("NONE");
- tester.get(IssueDao.class).insert(session, issue1, issue2);
- session.commit();
-
- org.sonar.server.search.Result<Issue> result = service.search(IssueQuery.builder().build(), new QueryContext());
- assertThat(result.getHits()).hasSize(2);
- assertThat(result.getFacets()).isEmpty();
-
- result = service.search(IssueQuery.builder().build(), new QueryContext().setFacet(true));
- assertThat(result.getFacets().keySet()).hasSize(4);
- assertThat(result.getFacetKeys("actionPlan")).hasSize(2);
- }
-
- @Test
- public void do_transition() {
- IssueDto issue = getIssue();
- tester.get(IssueDao.class).insert(session, issue);
- session.commit();
-
- assertThat(db.issueDao().getByKey(session, issue.getKey())).isNotNull();
-
- IssueTesting.assertIsEquivalent(issue, indexClient.get(IssueIndex.class).getByKey(issue.getKey()));
-
- service.doTransition(issue.getKey(), DefaultTransitions.CONFIRM, userSession);
- Issue issueDoc = indexClient.get(IssueIndex.class).getByKey(issue.getKey());
- assertThat(issueDoc.status()).isEqualTo(Issue.STATUS_CONFIRMED);
- }
-
- private IssueDto getIssue() {
- return new IssueDto()
- .setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
- .setIssueUpdateDate(DateUtils.parseDate("2014-12-04"))
- .setRule(rule)
- .setDebt(10L)
- .setRootComponent(project)
- .setComponent(resource)
- .setStatus(Issue.STATUS_OPEN)
- .setResolution(null)
- .setSeverity(Severity.MAJOR)
- .setKee(UUID.randomUUID().toString());
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/OldDefaultIssueServiceTest.java
index 4f555e56a9b..ceb1db14f4b 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/OldDefaultIssueServiceTest.java
@@ -46,6 +46,7 @@ import org.sonar.core.issue.db.IssueDao;
import org.sonar.core.issue.db.IssueStorage;
import org.sonar.core.issue.workflow.IssueWorkflow;
import org.sonar.core.issue.workflow.Transition;
+import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.preview.PreviewCache;
import org.sonar.core.resource.ResourceDao;
@@ -55,6 +56,7 @@ import org.sonar.core.rule.RuleDto;
import org.sonar.core.user.AuthorizationDao;
import org.sonar.core.user.DefaultUser;
import org.sonar.server.issue.actionplan.ActionPlanService;
+import org.sonar.server.user.MockUserSession;
import org.sonar.server.user.UserSession;
import java.util.Collections;
@@ -71,7 +73,7 @@ import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.*;
@RunWith(MockitoJUnitRunner.class)
-public class IssueServiceTest {
+public class OldDefaultIssueServiceTest {
@Mock
DefaultIssueFinder finder;
@@ -106,7 +108,6 @@ public class IssueServiceTest {
@Mock
UserFinder userFinder;
- @Mock
UserSession userSession;
@Mock
@@ -122,13 +123,16 @@ public class IssueServiceTest {
DefaultIssue issue = new DefaultIssue().setKey("ABCD");
- IssueService issueService;
+ OldIssueService issueService;
@Before
public void before() {
- when(userSession.isLoggedIn()).thenReturn(true);
- when(userSession.userId()).thenReturn(10);
- when(userSession.login()).thenReturn("arthur");
+ userSession = MockUserSession.set()
+ .setLogin("arthur")
+ .setUserId(10)
+ .setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN)
+ .addProjectPermissions(UserRole.USER, project.getKey())
+ .addProjectPermissions(UserRole.ISSUE_ADMIN, project.getKey());
when(authorizationDao.isAuthorizedComponentKey(anyString(), eq(10), anyString())).thenReturn(true);
when(finder.find(any(IssueQuery.class))).thenReturn(issueQueryResult);
@@ -138,7 +142,7 @@ public class IssueServiceTest {
when(resource.getKey()).thenReturn("org.sonar.Sample");
when(project.getKey()).thenReturn("Sample");
- issueService = new IssueService(finder, workflow, issueStorage, issueUpdater, issueNotifications, actionPlanService, ruleFinder, resourceDao, issueDao,
+ issueService = new OldIssueService(finder, workflow, issueStorage, issueUpdater, issueNotifications, actionPlanService, ruleFinder, resourceDao, issueDao,
authorizationDao, userFinder, mock(PreviewCache.class));
}
@@ -172,7 +176,7 @@ public class IssueServiceTest {
List<Transition> transitions = newArrayList(transition);
when(workflow.outTransitions(issue)).thenReturn(transitions);
- List<Transition> result = issueService.listTransitions("ABCD", userSession);
+ List<Transition> result = issueService.listTransitions("ABCD");
assertThat(result).hasSize(1);
assertThat(result.get(0)).isEqualTo(transition);
}
@@ -182,7 +186,7 @@ public class IssueServiceTest {
when(issueQueryResult.first()).thenReturn(null);
when(issueQueryResult.issues()).thenReturn(newArrayList((Issue) new DefaultIssue()));
- assertThat(issueService.listTransitions("ABCD", userSession)).isEmpty();
+ assertThat(issueService.listTransitions("ABCD")).isEmpty();
verifyZeroInteractions(workflow);
}
@@ -190,7 +194,7 @@ public class IssueServiceTest {
public void do_transition() {
when(workflow.doTransition(eq(issue), eq(transition.key()), any(IssueChangeContext.class))).thenReturn(true);
- Issue result = issueService.doTransition("ABCD", transition.key(), userSession);
+ Issue result = issueService.doTransition("ABCD", transition.key());
assertThat(result).isNotNull();
ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
@@ -208,7 +212,7 @@ public class IssueServiceTest {
public void not_do_transition() {
when(workflow.doTransition(eq(issue), eq(transition.key()), any(IssueChangeContext.class))).thenReturn(false);
- Issue result = issueService.doTransition("ABCD", transition.key(), userSession);
+ Issue result = issueService.doTransition("ABCD", transition.key());
assertThat(result).isNotNull();
verify(workflow).doTransition(eq(issue), eq(transition.key()), any(IssueChangeContext.class));
verifyZeroInteractions(issueStorage);
@@ -217,9 +221,9 @@ public class IssueServiceTest {
@Test
public void fail_do_transition_if_not_logged() {
- when(userSession.isLoggedIn()).thenReturn(false);
+ MockUserSession.set();
try {
- issueService.doTransition("ABCD", transition.key(), userSession);
+ issueService.doTransition("ABCD", transition.key());
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("User is not logged in");
@@ -235,7 +239,7 @@ public class IssueServiceTest {
when(userFinder.findByLogin(assignee)).thenReturn(user);
when(issueUpdater.assign(eq(issue), eq(user), any(IssueChangeContext.class))).thenReturn(true);
- Issue result = issueService.assign("ABCD", assignee, userSession);
+ Issue result = issueService.assign("ABCD", assignee);
assertThat(result).isNotNull();
ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
@@ -253,7 +257,7 @@ public class IssueServiceTest {
public void unassign() {
when(issueUpdater.assign(eq(issue), eq((User) null), any(IssueChangeContext.class))).thenReturn(true);
- Issue result = issueService.assign("ABCD", null, userSession);
+ Issue result = issueService.assign("ABCD", null);
assertThat(result).isNotNull();
ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
@@ -276,7 +280,7 @@ public class IssueServiceTest {
when(userFinder.findByLogin(assignee)).thenReturn(user);
when(issueUpdater.assign(eq(issue), eq(user), any(IssueChangeContext.class))).thenReturn(false);
- Issue result = issueService.assign("ABCD", assignee, userSession);
+ Issue result = issueService.assign("ABCD", assignee);
assertThat(result).isNotNull();
verify(issueUpdater).assign(eq(issue), eq(user), any(IssueChangeContext.class));
@@ -291,7 +295,7 @@ public class IssueServiceTest {
when(userFinder.findByLogin(assignee)).thenReturn(null);
try {
- issueService.assign("ABCD", assignee, userSession);
+ issueService.assign("ABCD", assignee);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown user: perceval");
@@ -311,7 +315,7 @@ public class IssueServiceTest {
when(actionPlanService.findByKey(actionPlanKey, userSession)).thenReturn(actionPlan);
when(issueUpdater.plan(eq(issue), eq(actionPlan), any(IssueChangeContext.class))).thenReturn(true);
- Issue result = issueService.plan("ABCD", actionPlanKey, userSession);
+ Issue result = issueService.plan("ABCD", actionPlanKey);
assertThat(result).isNotNull();
ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
@@ -329,7 +333,7 @@ public class IssueServiceTest {
public void unplan() {
when(issueUpdater.plan(eq(issue), eq((ActionPlan) null), any(IssueChangeContext.class))).thenReturn(true);
- Issue result = issueService.plan("ABCD", null, userSession);
+ Issue result = issueService.plan("ABCD", null);
assertThat(result).isNotNull();
ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
@@ -353,7 +357,7 @@ public class IssueServiceTest {
when(actionPlanService.findByKey(actionPlanKey, userSession)).thenReturn(actionPlan);
when(issueUpdater.plan(eq(issue), eq(actionPlan), any(IssueChangeContext.class))).thenReturn(false);
- Issue result = issueService.plan("ABCD", actionPlanKey, userSession);
+ Issue result = issueService.plan("ABCD", actionPlanKey);
assertThat(result).isNotNull();
verify(issueUpdater).plan(eq(issue), eq(actionPlan), any(IssueChangeContext.class));
verifyZeroInteractions(issueStorage);
@@ -366,7 +370,7 @@ public class IssueServiceTest {
when(actionPlanService.findByKey(actionPlanKey, userSession)).thenReturn(null);
try {
- issueService.plan("ABCD", actionPlanKey, userSession);
+ issueService.plan("ABCD", actionPlanKey);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown action plan: EFGH");
@@ -382,7 +386,7 @@ public class IssueServiceTest {
String severity = "MINOR";
when(issueUpdater.setManualSeverity(eq(issue), eq(severity), any(IssueChangeContext.class))).thenReturn(true);
- Issue result = issueService.setSeverity("ABCD", severity, userSession);
+ Issue result = issueService.setSeverity("ABCD", severity);
assertThat(result).isNotNull();
ArgumentCaptor<IssueChangeContext> measureCaptor = ArgumentCaptor.forClass(IssueChangeContext.class);
@@ -401,7 +405,7 @@ public class IssueServiceTest {
String severity = "MINOR";
when(issueUpdater.setManualSeverity(eq(issue), eq(severity), any(IssueChangeContext.class))).thenReturn(false);
- Issue result = issueService.setSeverity("ABCD", severity, userSession);
+ Issue result = issueService.setSeverity("ABCD", severity);
assertThat(result).isNotNull();
verify(issueUpdater).setManualSeverity(eq(issue), eq(severity), any(IssueChangeContext.class));
verifyZeroInteractions(issueStorage);
@@ -415,7 +419,7 @@ public class IssueServiceTest {
when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(resource);
when(resourceDao.getRootProjectByComponentKey(anyString())).thenReturn(project);
- Issue result = issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, "Fix it", null, null, userSession);
+ Issue result = issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, "Fix it", null, null);
assertThat(result).isNotNull();
assertThat(result.message()).isEqualTo("Fix it");
assertThat(result.creationDate()).isNotNull();
@@ -432,7 +436,7 @@ public class IssueServiceTest {
when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(resource);
when(resourceDao.getRootProjectByComponentKey(anyString())).thenReturn(project);
- Issue result = issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, "", null, null, userSession);
+ Issue result = issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, "", null, null);
assertThat(result).isNotNull();
assertThat(result.message()).isEqualTo("Manual Rule");
assertThat(result.creationDate()).isNotNull();
@@ -451,7 +455,7 @@ public class IssueServiceTest {
when(authorizationDao.isAuthorizedComponentKey(anyString(), eq(10), anyString())).thenReturn(false);
try {
- issueService.createManualIssue("org.sonar.Sample", ruleKey, null, null, null, null, userSession);
+ issueService.createManualIssue("org.sonar.Sample", ruleKey, null, null, null, null);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("User does not have the required role");
@@ -465,7 +469,7 @@ public class IssueServiceTest {
RuleKey ruleKey = RuleKey.of("squid", "s100");
try {
- issueService.createManualIssue("org.sonar.Sample", ruleKey, null, null, null, null, userSession);
+ issueService.createManualIssue("org.sonar.Sample", ruleKey, null, null, null, null);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Issues can be created only on rules marked as 'manual': squid:s100");
@@ -481,7 +485,7 @@ public class IssueServiceTest {
RuleKey ruleKey = RuleKey.of("manual", "manualRuleKey");
when(ruleFinder.findByKey(ruleKey)).thenReturn(null);
try {
- issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, null, null, null, userSession);
+ issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, null, null, null);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown rule: manual:manualRuleKey");
@@ -495,7 +499,7 @@ public class IssueServiceTest {
when(ruleFinder.findByKey(ruleKey)).thenReturn(Rule.create("manual", "manualRuleKey"));
when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(null);
try {
- issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, null, null, null, userSession);
+ issueService.createManualIssue("org.sonar.Sample", RuleKey.of("manual", "manualRuleKey"), null, null, null, null);
fail();
} catch (Exception e) {
assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("Unknown component: org.sonar.Sample");
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/PublicRubyIssueServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/PublicRubyDefaultIssueServiceTest.java
index 95bc3a3fcf2..27d10b67c22 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/PublicRubyIssueServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/PublicRubyDefaultIssueServiceTest.java
@@ -38,7 +38,7 @@ import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.*;
-public class PublicRubyIssueServiceTest {
+public class PublicRubyDefaultIssueServiceTest {
IssueFinder finder = mock(IssueFinder.class);
PublicRubyIssueService facade = new PublicRubyIssueService(finder);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java
index b2a231eb694..7cae13f4c4d 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueBackendMediumTest.java
@@ -50,7 +50,8 @@ import static org.fest.assertions.Assertions.assertThat;
public class IssueBackendMediumTest {
@ClassRule
- public static ServerTester tester = new ServerTester();
+ public static ServerTester tester = new ServerTester()
+ .setProperty("sonar.issues.use_es_backend", "true");
DbClient dbClient;
IndexClient indexClient;
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueDaoTest.java
index 44d4efb6b31..5034e196290 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueDaoTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueDaoTest.java
@@ -23,15 +23,20 @@ import com.google.common.collect.ImmutableMap;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.issue.db.IssueDto;
import org.sonar.core.persistence.AbstractDaoTestCase;
import org.sonar.core.persistence.DbSession;
+import org.sonar.server.rule.RuleTesting;
import java.util.Date;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class IssueDaoTest extends AbstractDaoTestCase {
@@ -52,8 +57,41 @@ public class IssueDaoTest extends AbstractDaoTestCase {
}
@Test
+ public void get_by_key() {
+ setupData("shared", "get_by_key");
+
+ IssueDto issue = dao.getByKey(session, "ABCDE");
+ assertThat(issue.getKee()).isEqualTo("ABCDE");
+ assertThat(issue.getId()).isEqualTo(100L);
+ assertThat(issue.getComponentId()).isEqualTo(401);
+ assertThat(issue.getRootComponentId()).isEqualTo(399);
+ assertThat(issue.getRuleId()).isEqualTo(500);
+ assertThat(issue.getSeverity()).isEqualTo("BLOCKER");
+ assertThat(issue.isManualSeverity()).isFalse();
+ assertThat(issue.getMessage()).isNull();
+ assertThat(issue.getLine()).isEqualTo(200);
+ assertThat(issue.getEffortToFix()).isEqualTo(4.2);
+ assertThat(issue.getStatus()).isEqualTo("OPEN");
+ assertThat(issue.getResolution()).isEqualTo("FIXED");
+ assertThat(issue.getChecksum()).isEqualTo("XXX");
+ assertThat(issue.getAuthorLogin()).isEqualTo("karadoc");
+ assertThat(issue.getReporter()).isEqualTo("arthur");
+ assertThat(issue.getAssignee()).isEqualTo("perceval");
+ assertThat(issue.getIssueAttributes()).isEqualTo("JIRA=FOO-1234");
+ assertThat(issue.getIssueCreationDate()).isNotNull();
+ assertThat(issue.getIssueUpdateDate()).isNotNull();
+ assertThat(issue.getIssueCloseDate()).isNotNull();
+ assertThat(issue.getCreatedAt()).isNotNull();
+ assertThat(issue.getUpdatedAt()).isNotNull();
+ assertThat(issue.getRuleRepo()).isEqualTo("squid");
+ assertThat(issue.getRule()).isEqualTo("AvoidCycle");
+ assertThat(issue.getComponentKey()).isEqualTo("Action.java");
+ assertThat(issue.getRootComponentKey()).isEqualTo("struts");
+ }
+
+ @Test
public void find_after_dates() throws Exception {
- setupData("shared", "should_select_all");
+ setupData("shared", "some_issues");
Date t0 = new Date(0);
assertThat(dao.findAfterDate(session, t0)).hasSize(3);
@@ -68,4 +106,76 @@ public class IssueDaoTest extends AbstractDaoTestCase {
assertThat(dao.findAfterDate(session, DateUtils.parseDate("2014-01-01"), ImmutableMap.of("project", "struts"))).hasSize(1);
}
+
+ @Test
+ public void insert() throws Exception {
+ when(system2.now()).thenReturn(DateUtils.parseDate("2013-05-22").getTime());
+
+ IssueDto dto = new IssueDto();
+ dto.setComponent(new ComponentDto().setKey("struts:Action").setId(123L));
+ dto.setRootComponent(new ComponentDto().setKey("struts").setId(100L));
+ dto.setRule(RuleTesting.newDto(RuleKey.of("squid", "S001")).setId(200));
+ dto.setKee("ABCDE");
+ dto.setLine(500);
+ dto.setEffortToFix(3.14);
+ dto.setDebt(10L);
+ dto.setResolution("FIXED");
+ dto.setStatus("RESOLVED");
+ dto.setSeverity("BLOCKER");
+ dto.setReporter("emmerik");
+ dto.setAuthorLogin("morgan");
+ dto.setAssignee("karadoc");
+ dto.setActionPlanKey("current_sprint");
+ dto.setIssueAttributes("JIRA=FOO-1234");
+ dto.setChecksum("123456789");
+ dto.setMessage("the message");
+
+ dto.setIssueCreationDate(DateUtils.parseDate("2013-05-18"));
+ dto.setIssueUpdateDate(DateUtils.parseDate("2013-05-19"));
+ dto.setIssueCloseDate(DateUtils.parseDate("2013-05-20"));
+ dto.setCreatedAt(DateUtils.parseDate("2013-05-21"));
+ dto.setUpdatedAt(DateUtils.parseDate("2013-05-22"));
+
+ dao.insert(session, dto);
+ session.commit();
+
+ checkTables("insert", new String[]{"id"}, "issues");
+ }
+
+ @Test
+ public void update() throws Exception {
+ when(system2.now()).thenReturn(DateUtils.parseDate("2013-05-22").getTime());
+
+ setupData("update");
+
+ IssueDto dto = new IssueDto();
+ dto.setComponent(new ComponentDto().setKey("struts:Action").setId(123L));
+ dto.setRootComponent(new ComponentDto().setKey("struts").setId(101L));
+ dto.setRule(RuleTesting.newDto(RuleKey.of("squid", "S001")).setId(200));
+ dto.setKee("ABCDE");
+ dto.setLine(500);
+ dto.setEffortToFix(3.14);
+ dto.setDebt(10L);
+ dto.setResolution("FIXED");
+ dto.setStatus("RESOLVED");
+ dto.setSeverity("BLOCKER");
+ dto.setReporter("emmerik");
+ dto.setAuthorLogin("morgan");
+ dto.setAssignee("karadoc");
+ dto.setActionPlanKey("current_sprint");
+ dto.setIssueAttributes("JIRA=FOO-1234");
+ dto.setChecksum("123456789");
+ dto.setMessage("the message");
+
+ dto.setIssueCreationDate(DateUtils.parseDate("2013-05-18"));
+ dto.setIssueUpdateDate(DateUtils.parseDate("2013-05-19"));
+ dto.setIssueCloseDate(DateUtils.parseDate("2013-05-20"));
+ dto.setCreatedAt(DateUtils.parseDate("2013-05-21"));
+ dto.setUpdatedAt(DateUtils.parseDate("2013-05-22"));
+
+ dao.update(session, dto);
+ session.commit();
+
+ checkTables("update", new String[]{"id"}, "issues");
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueAuthorizationIndexMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueAuthorizationIndexMediumTest.java
index 0895eedaa5b..6d9942bbbc7 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueAuthorizationIndexMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueAuthorizationIndexMediumTest.java
@@ -42,7 +42,8 @@ import static org.fest.assertions.Assertions.assertThat;
public class IssueAuthorizationIndexMediumTest {
@ClassRule
- public static ServerTester tester = new ServerTester();
+ public static ServerTester tester = new ServerTester()
+ .setProperty("sonar.issues.use_es_backend", "true");
DbClient db;
DbSession session;
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java
index 0fdc78077e7..fb95a3f198c 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/index/IssueIndexMediumTest.java
@@ -54,7 +54,8 @@ import static org.fest.assertions.Assertions.assertThat;
public class IssueIndexMediumTest {
@ClassRule
- public static ServerTester tester = new ServerTester();
+ public static ServerTester tester = new ServerTester()
+ .setProperty("sonar.issues.use_es_backend", "true");
DbClient db;
DbSession session;
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueActionsWriterTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueActionsWriterTest.java
index bb8d97e87b0..0970c222332 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueActionsWriterTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueActionsWriterTest.java
@@ -37,12 +37,10 @@ import org.sonar.core.issue.workflow.Transition;
import org.sonar.server.issue.ActionService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.user.MockUserSession;
-import org.sonar.server.user.UserSession;
import java.io.StringWriter;
import static com.google.common.collect.Lists.newArrayList;
-import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -77,8 +75,7 @@ public class IssueActionsWriterTest {
"{\"actions\": " +
"[" +
"\"comment\", \"assign\", \"assign_to_me\", \"plan\", \"set_severity\"\n" +
- "]}"
- );
+ "]}");
}
@Test
@@ -98,8 +95,7 @@ public class IssueActionsWriterTest {
"{\"actions\": " +
"[" +
"\"comment\", \"assign\", \"assign_to_me\", \"plan\", \"link-to-jira\"\n" +
- "]}"
- );
+ "]}");
}
@Test
@@ -117,8 +113,7 @@ public class IssueActionsWriterTest {
"{\"actions\": " +
"[" +
"\"comment\"" +
- "]}"
- );
+ "]}");
}
@Test
@@ -132,8 +127,7 @@ public class IssueActionsWriterTest {
MockUserSession.set();
testActions(issue,
- "{\"actions\": []}"
- );
+ "{\"actions\": []}");
}
@Test
@@ -151,8 +145,7 @@ public class IssueActionsWriterTest {
"{\"actions\": " +
"[" +
"\"comment\", \"assign\", \"plan\"\n" +
- "]}"
- );
+ "]}");
}
@Test
@@ -163,14 +156,13 @@ public class IssueActionsWriterTest {
.setProjectKey("sample")
.setRuleKey(RuleKey.of("squid", "AvoidCycle"));
- when(issueService.listTransitions(eq(issue), any(UserSession.class))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
+ when(issueService.listTransitions(eq(issue))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
MockUserSession.set().setLogin("john");
testTransitions(issue,
"{\"transitions\": [\n" +
" \"reopen\"\n" +
- " ]}"
- );
+ " ]}");
}
@Test
@@ -184,8 +176,7 @@ public class IssueActionsWriterTest {
MockUserSession.set().setLogin("john");
testTransitions(issue,
- "{\"transitions\": []}"
- );
+ "{\"transitions\": []}");
}
private void testActions(Issue issue, String expected) throws JSONException {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueSearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueSearchActionTest.java
index 95c8ff3da4d..9325f7745c3 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueSearchActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueSearchActionTest.java
@@ -52,7 +52,6 @@ import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.issue.ActionService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.user.MockUserSession;
-import org.sonar.server.user.UserSession;
import org.sonar.server.ws.WsTester;
import java.util.*;
@@ -243,7 +242,7 @@ public class IssueSearchActionTest {
issues.add(issue);
MockUserSession.set().setLogin("john");
- when(issueService.listTransitions(eq(issue), any(UserSession.class))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
+ when(issueService.listTransitions(eq(issue))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
result.addActionPlans(newArrayList((ActionPlan) new DefaultActionPlan().setKey("AP-ABCD").setName("1.0")));
diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java
index 2871fa8cd7c..66a73144b72 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java
@@ -53,7 +53,6 @@ import org.sonar.server.issue.IssueChangelog;
import org.sonar.server.issue.IssueChangelogService;
import org.sonar.server.issue.IssueService;
import org.sonar.server.user.MockUserSession;
-import org.sonar.server.user.UserSession;
import org.sonar.server.ws.WsTester;
import java.util.ArrayList;
@@ -431,7 +430,7 @@ public class IssueShowActionTest {
.setResolution("FIXED");
issues.add(issue);
- when(issueService.listTransitions(eq(issue), any(UserSession.class))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
+ when(issueService.listTransitions(eq(issue))).thenReturn(newArrayList(Transition.create("reopen", "RESOLVED", "REOPEN")));
MockUserSession.set().setLogin("john");
WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issue.key());
diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java
index d86c17e1ff8..6cfd273bce4 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java
@@ -97,6 +97,7 @@ public class RuleTesting {
public static RuleDto newManualRule(String manualKey){
return new RuleDto().setRuleKey(manualKey)
+ .setName("Name " + manualKey)
.setRepositoryKey("manual")
.setDescription("Description " + manualKey)
.setStatus(RuleStatus.READY);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/search/IndexSynchronizerMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/search/IndexSynchronizerMediumTest.java
index 8048b57beca..1e313236343 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/search/IndexSynchronizerMediumTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/search/IndexSynchronizerMediumTest.java
@@ -23,6 +23,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
+import org.sonar.api.config.Settings;
import org.sonar.api.rule.RuleKey;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.db.DbClient;
@@ -36,7 +37,8 @@ import static org.fest.assertions.Assertions.assertThat;
public class IndexSynchronizerMediumTest {
@ClassRule
- public static ServerTester tester = new ServerTester();
+ public static ServerTester tester = new ServerTester()
+ .setProperty("sonar.issues.use_es_backend", "true");
IndexSynchronizer synchronizer;
DbClient dbClient;
@@ -50,7 +52,7 @@ public class IndexSynchronizerMediumTest {
indexClient = tester.get(IndexClient.class);
platform = tester.get(Platform.class);
dbSession = dbClient.openSession(false);
- synchronizer = new IndexSynchronizer(dbClient, indexClient);
+ synchronizer = new IndexSynchronizer(dbClient, indexClient, tester.get(Settings.class));
tester.clearDbAndIndexes();
}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/get_by_key.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/get_by_key.xml
new file mode 100644
index 00000000000..9a5cc947917
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/get_by_key.xml
@@ -0,0 +1,28 @@
+<dataset>
+
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_id="401"
+ root_component_id="399"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="[null]"
+ line="200"
+ effort_to_fix="4.2"
+ status="OPEN"
+ resolution="FIXED"
+ checksum="XXX"
+ reporter="arthur"
+ assignee="perceval"
+ author_login="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ issue_creation_date="2013-04-16"
+ issue_update_date="2013-04-16"
+ issue_close_date="2013-04-16"
+ created_at="2013-04-16"
+ updated_at="2013-04-16"
+ />
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/insert-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/insert-result.xml
new file mode 100644
index 00000000000..3d736381a9e
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/insert-result.xml
@@ -0,0 +1,28 @@
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_id="123"
+ root_component_id="100"
+ rule_id="200"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="the message"
+ line="500"
+ effort_to_fix="3.14"
+ technical_debt="10"
+ status="RESOLVED"
+ resolution="FIXED"
+ checksum="123456789"
+ reporter="emmerik"
+ author_login="morgan"
+ assignee="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-19"
+ issue_close_date="2013-05-20"
+ created_at="2013-05-21"
+ updated_at="2013-05-22"
+ action_plan_key="current_sprint"
+ />
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/should_select_all.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/some_issues.xml
index 96ada68ee82..96ada68ee82 100644
--- a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/should_select_all.xml
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/some_issues.xml
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/update-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/update-result.xml
new file mode 100644
index 00000000000..a923dfa54e0
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/update-result.xml
@@ -0,0 +1,28 @@
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_id="123"
+ root_component_id="101"
+ rule_id="200"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="the message"
+ line="500"
+ effort_to_fix="3.14"
+ technical_debt="10"
+ status="RESOLVED"
+ resolution="FIXED"
+ checksum="123456789"
+ reporter="emmerik"
+ author_login="morgan"
+ assignee="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-19"
+ issue_close_date="2013-05-20"
+ created_at="[null]"
+ updated_at="2013-05-22"
+ action_plan_key="current_sprint"
+ />
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/update.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/update.xml
new file mode 100644
index 00000000000..4c6f701dc2c
--- /dev/null
+++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueDaoTest/update.xml
@@ -0,0 +1,28 @@
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_id="123"
+ root_component_id="100"
+ rule_id="200"
+ severity="INFO"
+ manual_severity="[false]"
+ message="old"
+ line="[null]"
+ effort_to_fix="[null]"
+ technical_debt="[null]"
+ status="OPEN"
+ resolution="[null]"
+ checksum="[null]"
+ reporter="[null]"
+ author_login="[null]"
+ assignee="[null]"
+ issue_attributes="[null]"
+ issue_creation_date="[null]"
+ issue_update_date="[null]"
+ issue_close_date="[null]"
+ created_at="[null]"
+ updated_at="2009-01-01"
+ action_plan_key="[null]"
+ />
+</dataset>
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/IssueNotifications.java b/sonar-core/src/main/java/org/sonar/core/issue/IssueNotifications.java
index 39b56b1644d..44262e5dc5d 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/IssueNotifications.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/IssueNotifications.java
@@ -37,6 +37,7 @@ import org.sonar.api.utils.DateUtils;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
import java.io.Serializable;
import java.util.List;
import java.util.Map;
@@ -71,7 +72,14 @@ public class IssueNotifications implements BatchComponent, ServerComponent {
public List<Notification> sendChanges(DefaultIssue issue, IssueChangeContext context, IssueQueryResult queryResult) {
Map<DefaultIssue, Rule> issues = Maps.newHashMap();
issues.put(issue, queryResult.rule(issue));
- return sendChanges(issues, context, queryResult.project(issue), queryResult.component(issue));
+ return sendChanges(issue, context, queryResult.rule(issue), queryResult.project(issue), queryResult.component(issue));
+ }
+
+ @CheckForNull
+ public List<Notification> sendChanges(DefaultIssue issue, IssueChangeContext context, Rule rule, Component project, @Nullable Component component) {
+ Map<DefaultIssue, Rule> issues = Maps.newHashMap();
+ issues.put(issue, rule);
+ return sendChanges(issues, context, project, component);
}
@CheckForNull
@@ -131,6 +139,7 @@ public class IssueNotifications implements BatchComponent, ServerComponent {
return notification;
}
+ @CheckForNull
private String ruleName(@Nullable Rule rule) {
// this code should definitely be shared in api
if (rule == null) {
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java
index 63278903bf2..fa67f6872a9 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java
@@ -136,7 +136,7 @@ public final class IssueDto extends Dto<String> implements Serializable {
}
/**
- * @deprecated please use setRootComponent;
+ * @deprecated please use setRootComponent
*/
@Deprecated
public IssueDto setRootComponentId(Long rootComponentId) {
@@ -349,6 +349,10 @@ public final class IssueDto extends Dto<String> implements Serializable {
return ruleRepo;
}
+ public RuleKey getRuleKey(){
+ return RuleKey.of(ruleRepo, ruleKey);
+ }
+
public String getComponentKey() {
return componentKey;
}
@@ -369,6 +373,8 @@ public final class IssueDto extends Dto<String> implements Serializable {
/**
* Should only be used to persist in E/S
+ *
+ * Please use {@link #setRule(org.sonar.core.rule.RuleDto)} instead
*/
public IssueDto setRuleKey(String repo, String rule) {
this.ruleRepo = repo;
@@ -378,6 +384,8 @@ public final class IssueDto extends Dto<String> implements Serializable {
/**
* Should only be used to persist in E/S
+ *
+ * Please use {@link #setComponent(org.sonar.core.component.ComponentDto)} instead
*/
public IssueDto setComponentKey(String componentKey) {
this.componentKey = componentKey;
@@ -386,6 +394,8 @@ public final class IssueDto extends Dto<String> implements Serializable {
/**
* Should only be used to persist in E/S
+ *
+ * Please use {@link #setRootComponent(org.sonar.core.component.ComponentDto)} instead
*/
public IssueDto setRootComponentKey(String rootComponentKey) {
this.rootComponentKey = rootComponentKey;
@@ -474,7 +484,7 @@ public final class IssueDto extends Dto<String> implements Serializable {
issue.setComponentId(componentId);
issue.setProjectKey(rootComponentKey);
issue.setManualSeverity(manualSeverity);
- issue.setRuleKey(RuleKey.of(ruleRepo, ruleKey));
+ issue.setRuleKey(getRuleKey());
issue.setActionPlanKey(actionPlanKey);
issue.setAuthorLogin(authorLogin);
issue.setNew(false);
diff --git a/sonar-core/src/main/java/org/sonar/core/permission/PermissionFacade.java b/sonar-core/src/main/java/org/sonar/core/permission/PermissionFacade.java
index 6bf273c5176..7fb5c14598d 100644
--- a/sonar-core/src/main/java/org/sonar/core/permission/PermissionFacade.java
+++ b/sonar-core/src/main/java/org/sonar/core/permission/PermissionFacade.java
@@ -42,6 +42,8 @@ import java.util.List;
* This facade wraps db operations related to permissions
*
* Should be removed when batch will no more create permission, and be replaced by a new PermissionService in module server (probably be a merge with InternalPermissionService)
+ *
+ * WARNING, this class is called by Views to apply default permission template on new views
*/
public class PermissionFacade implements TaskComponent, ServerComponent {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQueryResult.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQueryResult.java
index b327c37d4f3..37ea218345f 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQueryResult.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQueryResult.java
@@ -31,7 +31,9 @@ import java.util.List;
/**
* @since 3.6
+ * @deprecated since 5.0
*/
+@Deprecated
public interface IssueQueryResult {
/**
* Non-null paginated list of issues.