import org.sonar.api.utils.log.Loggers;
import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
import org.sonar.core.persistence.DbSession;
-import org.sonar.core.purge.IdUuidPair;
-import org.sonar.core.purge.PurgeConfiguration;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeListener;
-import org.sonar.core.purge.PurgeProfiler;
+import org.sonar.core.purge.*;
import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.properties.ProjectSettingsFactory;
import javax.annotation.Nullable;
private final PurgeListener purgeListener;
private final PurgeDao purgeDao;
private final DefaultPeriodCleaner periodCleaner;
- private final ProjectSettingsFactory projectSettingsFactory;
private final IssueIndex issueIndex;
public ProjectCleaner(PurgeDao purgeDao, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler, PurgeListener purgeListener,
- ProjectSettingsFactory projectSettingsFactory, IssueIndex issueIndex) {
+ IssueIndex issueIndex) {
this.purgeDao = purgeDao;
this.periodCleaner = periodCleaner;
this.profiler = profiler;
this.purgeListener = purgeListener;
- this.projectSettingsFactory = projectSettingsFactory;
this.issueIndex = issueIndex;
}
- public ProjectCleaner purge(DbSession session, IdUuidPair idUuidPair) {
+ public ProjectCleaner purge(DbSession session, IdUuidPair idUuidPair, Settings projectSettings) {
long start = System.currentTimeMillis();
profiler.reset();
- Settings settings = projectSettingsFactory.newProjectSettings(session, idUuidPair.getId());
- PurgeConfiguration configuration = newDefaultPurgeConfiguration(settings, idUuidPair);
+ PurgeConfiguration configuration = newDefaultPurgeConfiguration(projectSettings, idUuidPair);
- cleanHistoricalData(session, configuration.rootProjectIdUuid().getId(), settings);
+ cleanHistoricalData(session, configuration.rootProjectIdUuid().getId(), projectSettings);
doPurge(session, configuration);
deleteIndexedIssuesBefore(idUuidPair.getUuid(), configuration.maxLiveDateOfClosedIssues());
session.commit();
- logProfiling(start, settings);
+ logProfiling(start, projectSettings);
return this;
}
package org.sonar.server.computation;
-import com.google.common.base.Preconditions;
+import org.sonar.api.config.Settings;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.server.computation.step.ParseReportStep;
+import static com.google.common.base.Preconditions.checkState;
+
public class ComputationContext {
private final AnalysisReportDto reportDto;
private final ComponentDto project;
+ private Settings projectSettings;
/**
* Cache of analysis date as it can be accessed several times
}
public BatchReport.Metadata getReportMetadata() {
- Preconditions.checkState(reportMetadata != null, "Report metadata is available after execution of " + ParseReportStep.class);
+ checkState(reportMetadata != null, "Report metadata is available after execution of " + ParseReportStep.class);
return reportMetadata;
}
public void setReportMetadata(BatchReport.Metadata m) {
this.reportMetadata = m;
}
+
+ public Settings getProjectSettings() {
+ return projectSettings;
+ }
+
+ public void setProjectSettings(Settings projectSettings) {
+ checkState(this.projectSettings == null, "can't set project settings twice");
+ this.projectSettings = projectSettings;
+ }
}
import org.sonar.server.computation.step.ComputationStep;
import org.sonar.server.computation.step.ComputationSteps;
import org.sonar.server.db.DbClient;
+import org.sonar.server.properties.ProjectSettingsFactory;
public class ComputationService implements ServerComponent {
private final DbClient dbClient;
private final ComputationSteps steps;
private final ActivityService activityService;
+ private final ProjectSettingsFactory projectSettingsFactory;
- public ComputationService(DbClient dbClient, ComputationSteps steps, ActivityService activityService) {
+ public ComputationService(DbClient dbClient, ComputationSteps steps, ActivityService activityService, ProjectSettingsFactory projectSettingsFactory) {
this.dbClient = dbClient;
this.steps = steps;
this.activityService = activityService;
+ this.projectSettingsFactory = projectSettingsFactory;
}
public void process(AnalysisReportDto report) {
ComponentDto project = loadProject(report);
try {
ComputationContext context = new ComputationContext(report, project);
+ context.setProjectSettings(projectSettingsFactory.newProjectSettings(dbClient.openSession(false), project.getId()));
for (ComputationStep step : steps.orderedSteps()) {
if (ArrayUtils.contains(step.supportedProjectQualifiers(), context.getProject().qualifier())) {
Profiler stepProfiler = Profiler.create(LOG).startInfo(step.getDescription());
package org.sonar.server.computation.issue;
import com.google.common.collect.Sets;
+import org.sonar.api.CoreProperties;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.issue.internal.FieldDiffs;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.user.index.UserDoc;
+import org.sonar.server.user.index.UserIndex;
import org.sonar.server.util.cache.DiskCache;
+import javax.annotation.Nullable;
+
import java.util.Date;
public class IssueComputation {
+ private static final Logger LOG = Loggers.get(IssueComputation.class);
+
private final RuleCache ruleCache;
private final ScmAccountCache scmAccountCache;
private final SourceLinesCache linesCache;
private final DiskCache<DefaultIssue>.DiskAppender diskIssuesAppender;
+ private final UserIndex userIndex;
+ private boolean hasAssigneeBeenComputed = false;
+ private String defaultAssignee = null;
public IssueComputation(RuleCache ruleCache, SourceLinesCache linesCache, ScmAccountCache scmAccountCache,
- IssueCache issueCache) {
+ IssueCache issueCache, UserIndex userIndex) {
this.ruleCache = ruleCache;
this.linesCache = linesCache;
this.scmAccountCache = scmAccountCache;
+ this.userIndex = userIndex;
this.diskIssuesAppender = issueCache.newAppender();
}
public void processComponentIssues(ComputationContext context, String componentUuid, Iterable<BatchReport.Issue> issues) {
linesCache.init(componentUuid);
+ computeDefaultAssignee(context.getProjectSettings().getString(CoreProperties.DEFAULT_ISSUE_ASSIGNEE));
for (BatchReport.Issue reportIssue : issues) {
DefaultIssue issue = toDefaultIssue(context, componentUuid, reportIssue);
if (issue.isNew()) {
guessAuthor(issue);
- autoAssign(issue);
+ autoAssign(issue, defaultAssignee);
copyRuleTags(issue);
}
diskIssuesAppender.append(issue);
}
}
- private void autoAssign(DefaultIssue issue) {
+ private void autoAssign(DefaultIssue issue, @Nullable String defaultAssignee) {
// issue.assignee() can be not-null if the issue-assign-plugin is
// still installed and executed during analysis
if (issue.assignee() == null) {
if (scmAccount != null) {
issue.setAssignee(scmAccountCache.getNullable(scmAccount));
}
+ if (issue.assignee() == null && defaultAssignee != null) {
+ issue.setAssignee(defaultAssignee);
+ }
}
}
issue.setTags(Sets.union(rule.getTags(), rule.getSystemTags()));
}
+ private void computeDefaultAssignee(String login) {
+ if (hasAssigneeBeenComputed) {
+ return;
+ }
+
+ hasAssigneeBeenComputed = true;
+ UserDoc user = userIndex.getNullableByLogin(login);
+ if (user == null) {
+ LOG.info("the {} property was set with an unknown login: {}", CoreProperties.DEFAULT_ISSUE_ASSIGNEE, login);
+ } else {
+ defaultAssignee = login;
+ }
+ }
}
public void execute(ComputationContext context) {
DbSession session = dbClient.openSession(true);
try {
- projectCleaner.purge(session, new IdUuidPair(context.getProject().getId(), context.getProject().uuid()));
+ projectCleaner.purge(session, new IdUuidPair(context.getProject().getId(), context.getProject().uuid()), context.getProjectSettings());
session.commit();
} finally {
MyBatis.closeQuietly(session);
}
private Long getTargetedUser(DbSession session, String userLogin) {
- UserDto user = dbClient.userDao().selectActiveUserByLogin(userLogin, session);
+ UserDto user = dbClient.userDao().selectActiveUserByLogin(session, userLogin);
badRequestIfNullResult(user, OBJECT_TYPE_USER, userLogin);
return user.getId();
}
String login = profileActivity.login();
if (login != null) {
- UserDto user = db.userDao().selectActiveUserByLogin(login, session);
+ UserDto user = db.userDao().selectActiveUserByLogin(session, login);
profileActivity.authorName(user != null ? user.getName() : null);
}
result.getHits().add(profileActivity);
@Before
public void before() throws Exception {
this.projectSettingsFactory = mock(ProjectSettingsFactory.class);
- when(projectSettingsFactory.newProjectSettings(any(DbSession.class), any(Long.class))).thenReturn(settings);
- this.sut = new ProjectCleaner(dao, periodCleaner, profiler, purgeListener, projectSettingsFactory, issueIndex);
+ this.sut = new ProjectCleaner(dao, periodCleaner, profiler, purgeListener, issueIndex);
}
@Test
public void no_profiling_when_property_is_false() throws Exception {
settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, false);
- when(projectSettingsFactory.newProjectSettings(any(DbSession.class), any(Long.class))).thenReturn(settings);
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verify(profiler, never()).dump(anyLong(), any(Logger.class));
}
@Test
public void no_indexing_when_no_issue_to_delete() throws Exception {
- when(projectSettingsFactory.newProjectSettings(any(DbSession.class), any(Long.class))).thenReturn(settings);
-
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verifyZeroInteractions(issueIndex);
}
public void profiling_when_property_is_true() throws Exception {
settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, true);
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verify(profiler).dump(anyLong(), any(Logger.class));
}
public void call_period_cleaner_index_client_and_purge_dao() throws Exception {
settings.setProperty(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES, 5);
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verify(periodCleaner).clean(any(DbSession.class), any(Long.class), any(Settings.class));
verify(dao).purge(any(DbSession.class), any(PurgeConfiguration.class), any(PurgeListener.class));
public void if_dao_purge_fails_it_should_not_interrupt_program_execution() throws Exception {
doThrow(RuntimeException.class).when(dao).purge(any(DbSession.class), any(PurgeConfiguration.class), any(PurgeListener.class));
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verify(dao).purge(any(DbSession.class), any(PurgeConfiguration.class), any(PurgeListener.class));
}
public void if_profiler_cleaning_fails_it_should_not_interrupt_program_execution() throws Exception {
doThrow(RuntimeException.class).when(periodCleaner).clean(any(DbSession.class), anyLong(), any(Settings.class));
- sut.purge(mock(DbSession.class), mock(IdUuidPair.class));
+ sut.purge(mock(DbSession.class), mock(IdUuidPair.class), settings);
verify(periodCleaner).clean(any(DbSession.class), anyLong(), any(Settings.class));
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.computation;
+
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.computation.db.AnalysisReportDto;
+
+import static org.mockito.Mockito.mock;
+
+public class ComputationContextTest {
+
+ ComputationContext sut = new ComputationContext(mock(AnalysisReportDto.class), mock(ComponentDto.class));
+
+ @Test(expected = IllegalStateException.class)
+ public void getReportMetadata() throws Exception {
+ sut.getReportMetadata();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void setProjectSettings() throws Exception {
+ sut.setProjectSettings(mock(Settings.class));
+ sut.setProjectSettings(mock(Settings.class));
+ }
+}
\ No newline at end of file
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
+import org.mockito.Mockito;
import org.sonar.api.resources.Qualifiers;
import org.sonar.core.activity.Activity;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.server.computation.step.ComputationStep;
import org.sonar.server.computation.step.ComputationSteps;
import org.sonar.server.db.DbClient;
+import org.sonar.server.properties.ProjectSettingsFactory;
import java.util.Arrays;
when(steps.orderedSteps()).thenReturn(Arrays.asList(projectStep1, projectStep2, viewStep));
// load report from db and parse it
- ComputationService sut = new ComputationService(dbClient, steps, activityService);
+ ComputationService sut = new ComputationService(dbClient, steps, activityService, mock(ProjectSettingsFactory.class, Mockito.RETURNS_DEEP_STUBS));
AnalysisReportDto report = AnalysisReportDto.newForTests(1L);
report.setProjectKey("PROJECT_KEY");
assertThat(report.getStatus()).isNull();
doThrow(new UnsupportedOperationException()).when(projectStep1).execute(any(ComputationContext.class));
// load report from db and parse it
- ComputationService sut = new ComputationService(dbClient, steps, activityService);
+ ComputationService sut = new ComputationService(dbClient, steps, activityService, mock(ProjectSettingsFactory.class, Mockito.RETURNS_DEEP_STUBS));
AnalysisReportDto report = AnalysisReportDto.newForTests(1L);
report.setProjectKey("PROJECT_KEY");
try {
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterators;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.Mockito;
+import org.sonar.api.CoreProperties;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.internal.DefaultIssue;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.utils.System2;
+import org.sonar.api.utils.log.LogTester;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.computation.ComputationContext;
+import org.sonar.server.user.index.UserDoc;
+import org.sonar.server.user.index.UserIndex;
import java.io.IOException;
import java.util.Arrays;
@Rule
public TemporaryFolder temp = new TemporaryFolder();
+ @Rule
+ public LogTester logTester = new LogTester();
+
IssueComputation sut;
// inputs
.setRuleRepository(RULE_KEY.repository())
.setRuleKey(RULE_KEY.rule())
.setStatus(Issue.STATUS_OPEN);
+ ComputationContext context = mock(ComputationContext.class, Mockito.RETURNS_DEEP_STUBS);
+ UserIndex userIndex = mock(UserIndex.class);
// output
IssueCache outputIssues;
public void setUp() throws IOException {
when(ruleCache.get(RULE_KEY)).thenReturn(rule);
outputIssues = new IssueCache(temp.newFile(), System2.INSTANCE);
- sut = new IssueComputation(ruleCache, lineCache, scmAccountCache, outputIssues);
+ sut = new IssueComputation(ruleCache, lineCache, scmAccountCache, outputIssues, userIndex);
+ }
+
+ @After
+ public void after() throws Exception {
+ sut.afterReportProcessing();
}
@Test
verifyZeroInteractions(scmAccountCache);
}
+ @Test
+ public void assign_default_assignee_when_available() throws Exception {
+ inputIssue.setIsNew(true);
+ String wolinski = "wolinski";
+ when(context.getProjectSettings().getString(CoreProperties.DEFAULT_ISSUE_ASSIGNEE)).thenReturn(wolinski);
+ when(userIndex.getNullableByLogin(wolinski)).thenReturn(new UserDoc());
+
+ process();
+
+ assertThat(Iterators.getOnlyElement(outputIssues.traverse()).assignee()).isEqualTo(wolinski);
+ assertThat(logTester.logs()).doesNotContain(String.format("the %s property was set with an unknown login: %s", CoreProperties.DEFAULT_ISSUE_ASSIGNEE, wolinski));
+ }
+
+ @Test
+ public void do_not_assign_default_assignee_when_not_found_in_index() throws Exception {
+ inputIssue.setIsNew(true);
+ String wolinski = "wolinski";
+ when(context.getProjectSettings().getString(CoreProperties.DEFAULT_ISSUE_ASSIGNEE)).thenReturn(wolinski);
+ when(userIndex.getNullableByLogin(wolinski)).thenReturn(null);
+
+ process();
+
+ assertThat(Iterators.getOnlyElement(outputIssues.traverse()).assignee()).isNull();
+ assertThat(logTester.logs()).contains(String.format("the %s property was set with an unknown login: %s", CoreProperties.DEFAULT_ISSUE_ASSIGNEE, wolinski));
+ }
+
private void process() {
- sut.processComponentIssues(mock(ComputationContext.class, Mockito.RETURNS_DEEP_STUBS), "FILE_A", Arrays.asList(inputIssue.build()));
- sut.afterReportProcessing();
+ sut.processComponentIssues(context, "FILE_A", Arrays.asList(inputIssue.build()));
}
}
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
+import org.sonar.api.config.Settings;
import org.sonar.api.utils.ZipUtils;
import org.sonar.api.utils.internal.DefaultTempFolder;
import org.sonar.batch.protocol.Constants;
public class ParseReportStepTest {
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
@ClassRule
public static DbTester dbTester = new DbTester();
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+ ParseReportStep sut;
@Before
public void setUp() throws Exception {
@Test
public void extract_report_from_db_and_browse_components() throws Exception {
AnalysisReportDto reportDto = prepareAnalysisReportInDb();
-
-
IssueComputation issueComputation = mock(IssueComputation.class);
DbClient dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), new AnalysisReportDao());
- ParseReportStep step = new ParseReportStep(issueComputation, dbClient, new DefaultTempFolder(temp.newFolder()));
+ sut = new ParseReportStep(issueComputation, dbClient, new DefaultTempFolder(temp.newFolder()));
ComputationContext context = new ComputationContext(reportDto, mock(ComponentDto.class));
- step.execute(context);
+ context.setProjectSettings(mock(Settings.class, Mockito.RETURNS_DEEP_STUBS));
+
+ sut.execute(context);
// verify that all components are processed (currently only for issues)
verify(issueComputation).processComponentIssues(context, "PROJECT_UUID", Collections.<BatchReport.Issue>emptyList());
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
+import org.sonar.api.config.Settings;
import org.sonar.api.utils.DateUtils;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.component.SnapshotDto;
import org.sonar.core.computation.dbcleaner.ProjectCleaner;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
+import org.sonar.core.properties.PropertiesDao;
import org.sonar.core.properties.PropertyDto;
import org.sonar.server.component.ComponentTesting;
import org.sonar.server.component.SnapshotTesting;
import org.sonar.server.computation.ComputationContext;
import org.sonar.server.db.DbClient;
+import org.sonar.server.properties.ProjectSettingsFactory;
import org.sonar.server.tester.ServerTester;
import java.util.Date;
dbClient.propertiesDao().setProperty(new PropertyDto().setKey(DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS).setValue("52"));
dbSession.commit();
ComputationContext context = new ComputationContext(report, project);
+ context.setProjectSettings(new ProjectSettingsFactory(tester.get(Settings.class), tester.get(PropertiesDao.class)).newProjectSettings(dbSession, project.getId()));
// ACT
sut.execute(context);
dbClient.propertiesDao().setProperty(new PropertyDto().setKey(DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS).setValue("1").setResourceId(project.getId()));
dbSession.commit();
ComputationContext context = new ComputationContext(report, project);
+ context.setProjectSettings(new ProjectSettingsFactory(tester.get(Settings.class), tester.get(PropertiesDao.class)).newProjectSettings(dbSession, project.getId()));
// ACT
sut.execute(context);
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.mockito.Mockito;
+import org.sonar.api.config.Settings;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.computation.dbcleaner.ProjectCleaner;
sut.execute(context);
- verify(projectCleaner).purge(any(DbSession.class), any(IdUuidPair.class));
+ verify(projectCleaner).purge(any(DbSession.class), any(IdUuidPair.class), any(Settings.class));
}
}
.subCategory(CoreProperties.SUBCATEGORY_LOOKNFEEL)
.build(),
+ // ISSUES
+ PropertyDefinition.builder(CoreProperties.DEFAULT_ISSUE_ASSIGNEE)
+ .name("Default Assignee")
+ .description("Login assigned to a new issue if an assignee has not been found.")
+ .category(CoreProperties.CATEGORY_GENERAL)
+ .subCategory(CoreProperties.SUBCATEGORY_ISSUES)
+ .onQualifiers(Qualifiers.PROJECT)
+ .type(PropertyType.STRING)
+ .build(),
+
// BATCH
PropertyDefinition.builder(CoreProperties.CORE_VIOLATION_LOCALE_PROPERTY)
.subCategory(CoreProperties.SUBCATEGORY_DUPLICATIONS_EXCLUSIONS)
.multiValues(true)
.build()
- ));
+ ));
return defs;
}
}
public UserDto selectActiveUserByLogin(String login) {
DbSession session = mybatis.openSession(false);
try {
- return selectActiveUserByLogin(login, session);
+ return selectActiveUserByLogin(session, login);
} finally {
MyBatis.closeQuietly(session);
}
}
- public UserDto selectActiveUserByLogin(String login, DbSession session) {
+ @CheckForNull
+ public UserDto selectActiveUserByLogin(DbSession session, String login) {
UserMapper mapper = session.getMapper(UserMapper.class);
return mapper.selectUserByLogin(login);
}
public List<UserDto> selectUsersByLogins(List<String> logins) {
List<UserDto> users = Lists.newArrayList();
- SqlSession session = mybatis.openSession(false);
+ DbSession session = mybatis.openSession(false);
try {
users.addAll(selectUsersByLogins(session, logins));
} finally {
return users;
}
- public List<UserDto> selectUsersByLogins(SqlSession session, List<String> logins) {
+ public List<UserDto> selectUsersByLogins(DbSession session, List<String> logins) {
List<UserDto> users = Lists.newArrayList();
if (!logins.isEmpty()) {
UserMapper mapper = session.getMapper(UserMapper.class);
property.category.general.localization=Localization
property.category.general.databaseCleaner=Database Cleaner
property.category.general.looknfeel=Look & Feel
+property.category.general.issues=Issues
property.category.security=Security
property.category.security.encryption=Encryption
property.category.java=Java
*/
String SUBCATEGORY_LOOKNFEEL = "looknfeel";
+ /**
+ * @since 5.1
+ */
+ String SUBCATEGORY_ISSUES = "issues";
+
/**
* @since 4.0
*/
*/
String IMPORT_UNKNOWN_FILES_KEY = "sonar.import_unknown_files";
+ /**
+ * @since 5.1
+ */
+ String DEFAULT_ISSUE_ASSIGNEE = "sonar.issues.defaultAssigneeLogin";
+
}