diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2014-10-23 10:27:29 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2014-10-23 15:09:57 +0200 |
commit | dabfb5f4d87c195a7190a60c0d2f955324583f69 (patch) | |
tree | a3f6576304ecbad119cf930f6ded417bcaf682f8 | |
parent | 76bc2bfa058d721700fbb0c2900f9dab1fc61306 (diff) | |
download | sonarqube-dabfb5f4d87c195a7190a60c0d2f955324583f69.tar.gz sonarqube-dabfb5f4d87c195a7190a60c0d2f955324583f69.zip |
SONAR-5530 Add uuid in Issue Index
112 files changed, 1748 insertions, 848 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java index 2f6dbe2f900..f46e87baf76 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java @@ -183,7 +183,7 @@ public class IssueTrackingDecorator implements Decorator { Long debtInMinutes = ref.getDebt(); Duration previousTechnicalDebt = debtInMinutes != null ? Duration.create(debtInMinutes) : null; updater.setPastTechnicalDebt(issue, previousTechnicalDebt, changeContext); - updater.setPastProject(issue, ref.getRootComponentKey(), changeContext); + updater.setPastProject(issue, ref.getProjectKey(), changeContext); } } diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java index c2f20fc26cc..7d4bc08c27a 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java @@ -508,7 +508,7 @@ public class IssueTrackingDecoratorTest extends AbstractDaoTestCase { @Test public void merge_matched_issue() throws Exception { IssueDto previousIssue = new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle") - .setLine(10).setSeverity("MAJOR").setMessage("Message").setEffortToFix(1.5).setDebt(1L).setRootComponentKey("sample"); + .setLine(10).setSeverity("MAJOR").setMessage("Message").setEffortToFix(1.5).setDebt(1L).setProjectKey("sample"); DefaultIssue issue = new DefaultIssue(); IssueTrackingResult trackingResult = mock(IssueTrackingResult.class); diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java index 79b36089bc5..f03ec5a6cb4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentCleanerService.java @@ -45,15 +45,15 @@ public class ComponentCleanerService implements ServerComponent { throw new IllegalArgumentException("Only project can be deleted"); } purgeDao.deleteResourceTree(project.getId()); - deletePermissionIndexes(session, projectKey); + deletePermissionIndexes(session, project.uuid()); session.commit(); } finally { session.close(); } } - private void deletePermissionIndexes(DbSession session, String projectKey) { - dbClient.issueAuthorizationDao().deleteByKey(session, projectKey); + private void deletePermissionIndexes(DbSession session, String projectUuid) { + dbClient.issueAuthorizationDao().deleteByKey(session, projectUuid); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java index e6b2b4a0f1c..0a6569c79b8 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ComponentService.java @@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableMap; import org.sonar.api.ServerComponent; import org.sonar.api.web.UserRole; import org.sonar.core.component.AuthorizedComponentDto; +import org.sonar.core.component.ComponentDto; import org.sonar.core.persistence.DbSession; import org.sonar.core.preview.PreviewCache; import org.sonar.core.resource.ResourceDto; @@ -72,6 +73,25 @@ public class ComponentService implements ServerComponent { } } + public ComponentDto getByUuid(String uuid) { + DbSession session = dbClient.openSession(false); + try { + return dbClient.componentDao().getByUuid(session, uuid); + } finally { + session.close(); + } + } + + @CheckForNull + public ComponentDto getNullableByUuid(String uuid) { + DbSession session = dbClient.openSession(false); + try { + return dbClient.componentDao().getNullableByUuid(session, uuid); + } finally { + session.close(); + } + } + public void updateKey(String projectOrModuleKey, String newKey) { UserSession.get().checkComponentPermission(UserRole.ADMIN, projectOrModuleKey); diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java b/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java index 62ad40944e3..63dfbf04877 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/DefaultRubyComponentService.java @@ -33,6 +33,8 @@ import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.util.RubyUtils; +import javax.annotation.CheckForNull; + import java.util.Date; import java.util.List; import java.util.Locale; @@ -55,10 +57,16 @@ public class DefaultRubyComponentService implements RubyComponentService { } @Override + @CheckForNull public Component findByKey(String key) { return resourceDao.findByKey(key); } + @CheckForNull + public Component findByUuid(String uuid) { + return componentService.getNullableByUuid(uuid); + } + public Long createComponent(String kee, String name, String qualifier) { ComponentDto component = (ComponentDto) resourceDao.findByKey(kee); if (component != null) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java b/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java index 8e953b66774..8403977bc2c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java @@ -60,6 +60,20 @@ public class ComponentDao extends BaseDao<ComponentMapper, ComponentDto, String> return mapper(session).selectById(id); } + @CheckForNull + public ComponentDto getNullableByUuid(DbSession session, String uuid) { + return mapper(session).selectByUuid(uuid); + } + + @CheckForNull + public ComponentDto getByUuid(DbSession session, String uuid) { + ComponentDto componentDto = getNullableByUuid(session, uuid); + if (componentDto == null) { + throw new NotFoundException(String.format("Project with uuid '%s' not found", uuid)); + } + return componentDto; + } + public boolean existsById(Long id, DbSession session) { return mapper(session).countById(id) > 0; } @@ -90,11 +104,11 @@ public class ComponentDao extends BaseDao<ComponentMapper, ComponentDto, String> return mapper(session).findModulesByProject(projectKey); } - public List<ComponentDto> findSubProjectsByComponentKeys(DbSession session, Collection<String> keys) { + public List<ComponentDto> findSubProjectsByComponentUuids(DbSession session, Collection<String> keys) { if (keys.isEmpty()) { return Collections.emptyList(); } - return mapper(session).findSubProjectsByComponentKeys(keys); + return mapper(session).findSubProjectsByComponentUuids(keys); } public List<ComponentDto> getByIds(DbSession session, Collection<Long> ids) { @@ -110,6 +124,19 @@ public class ComponentDao extends BaseDao<ComponentMapper, ComponentDto, String> return components; } + public List<ComponentDto> getByUuids(DbSession session, Collection<String> uuids) { + if (uuids.isEmpty()) { + return Collections.emptyList(); + } + List<ComponentDto> components = newArrayList(); + List<List<String>> partitionList = Lists.partition(newArrayList(uuids), 1000); + for (List<String> partition : partitionList) { + List<ComponentDto> dtos = mapper(session).findByUuids(partition); + components.addAll(dtos); + } + return components; + } + @Override protected List<ComponentDto> doGetByKeys(DbSession session, Collection<String> keys) { return mapper(session).findByKeys(keys); diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/SynchronizeProjectPermissionsStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/SynchronizeProjectPermissionsStep.java index 559ce11566a..65efcd21924 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/SynchronizeProjectPermissionsStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/SynchronizeProjectPermissionsStep.java @@ -20,8 +20,10 @@ package org.sonar.server.computation; +import org.sonar.core.component.AuthorizedComponentDto; import org.sonar.core.computation.db.AnalysisReportDto; import org.sonar.core.persistence.DbSession; +import org.sonar.server.db.DbClient; import org.sonar.server.issue.index.IssueAuthorizationIndex; import org.sonar.server.permission.InternalPermissionService; import org.sonar.server.search.IndexClient; @@ -29,10 +31,12 @@ import org.sonar.server.search.IndexClient; public class SynchronizeProjectPermissionsStep implements AnalysisReportStep { private final IndexClient index; + private final DbClient dbClient; private final InternalPermissionService permissionService; - public SynchronizeProjectPermissionsStep(IndexClient index, InternalPermissionService permissionService) { + public SynchronizeProjectPermissionsStep(IndexClient index, DbClient dbClient, InternalPermissionService permissionService) { this.index = index; + this.dbClient = dbClient; this.permissionService = permissionService; } @@ -43,7 +47,9 @@ public class SynchronizeProjectPermissionsStep implements AnalysisReportStep { private void synchronizeProjectPermissionsIfNotFound(DbSession session, String projectKey) { if (index.get(IssueAuthorizationIndex.class).getNullableByKey(projectKey) == null) { - permissionService.synchronizePermissions(session, projectKey); + // TODO Remove this db call by inserting the project uuid in the report + AuthorizedComponentDto project = dbClient.componentDao().getAuthorizedComponentByKey(projectKey, session); + permissionService.synchronizePermissions(session, project.uuid()); session.commit(); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/MassUpdate.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/MassUpdate.java index 8013d9cff81..845b22c5d84 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/MassUpdate.java +++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/MassUpdate.java @@ -99,13 +99,13 @@ public class MassUpdate { } } - static class ProgressTask extends TimerTask { + public static class ProgressTask extends TimerTask { private static final Logger LOGGER = LoggerFactory.getLogger("DbMigration"); - private static final long PERIOD_MS = 60000L; + public static final long PERIOD_MS = 60000L; private final AtomicLong counter; private String rowName = "rows"; - ProgressTask(AtomicLong counter) { + public ProgressTask(AtomicLong counter) { this.counter = counter; } @@ -118,7 +118,7 @@ public class MassUpdate { log(); } - void log() { + public void log() { LOGGER.info(String.format("%d %s processed", counter.get(), rowName)); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigration.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigration.java index 222bd793fa9..4cbd1c62997 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigration.java +++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigration.java @@ -28,10 +28,13 @@ import org.sonar.core.persistence.migration.v50.Component; import org.sonar.core.persistence.migration.v50.Migration50Mapper; import org.sonar.server.db.DbClient; import org.sonar.server.db.migrations.DatabaseMigration; +import org.sonar.server.db.migrations.MassUpdate; import java.util.List; import java.util.Map; +import java.util.Timer; import java.util.UUID; +import java.util.concurrent.atomic.AtomicLong; import static com.google.common.collect.Maps.newHashMap; @@ -43,6 +46,8 @@ import static com.google.common.collect.Maps.newHashMap; public class PopulateProjectsUuidColumnsMigration implements DatabaseMigration { private final DbClient db; + private final AtomicLong counter = new AtomicLong(0L); + private final MassUpdate.ProgressTask progressTask = new MassUpdate.ProgressTask(counter); public PopulateProjectsUuidColumnsMigration(DbClient db) { this.db = db; @@ -50,6 +55,9 @@ public class PopulateProjectsUuidColumnsMigration implements DatabaseMigration { @Override public void execute() { + Timer timer = new Timer("Db Migration Progress"); + timer.schedule(progressTask, MassUpdate.ProgressTask.PERIOD_MS, MassUpdate.ProgressTask.PERIOD_MS); + DbSession session = db.openSession(true); try { Migration50Mapper mapper = session.getMapper(Migration50Mapper.class); @@ -91,12 +99,18 @@ public class PopulateProjectsUuidColumnsMigration implements DatabaseMigration { } mapper.updateComponentUuids(component); + counter.getAndIncrement(); } } session.commit(); + // log the total number of process rows + progressTask.log(); + } finally { session.close(); + timer.cancel(); + timer.purge(); } } 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 3934e2ffae1..1513c8b2936 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 @@ -22,11 +22,8 @@ package org.sonar.server.issue; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.base.Predicate; -import com.google.common.base.Splitter; import com.google.common.base.Strings; -import com.google.common.collect.Collections2; import com.google.common.collect.Iterables; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import org.apache.commons.lang.StringUtils; import org.sonar.api.ServerComponent; @@ -83,6 +80,7 @@ public class InternalRubyIssueService implements ServerComponent { private static final String ACTION_PLANS_ERRORS_ACTION_PLAN_DOES_NOT_EXIST_MESSAGE = "action_plans.errors.action_plan_does_not_exist"; private final IssueService issueService; + private final IssueQueryService issueQueryService; private final IssueCommentService commentService; private final IssueChangelogService changelogService; private final ActionPlanService actionPlanService; @@ -93,11 +91,13 @@ public class InternalRubyIssueService implements ServerComponent { public InternalRubyIssueService( IssueService issueService, + IssueQueryService issueQueryService, IssueCommentService commentService, IssueChangelogService changelogService, ActionPlanService actionPlanService, ResourceDao resourceDao, ActionService actionService, IssueFilterService issueFilterService, IssueBulkChangeService issueBulkChangeService) { this.issueService = issueService; + this.issueQueryService = issueQueryService; this.commentService = commentService; this.changelogService = changelogService; this.actionPlanService = actionPlanService; @@ -112,7 +112,7 @@ public class InternalRubyIssueService implements ServerComponent { } public Map<String, Integer> findIssueAssignees(Map<String, Object> params) { - return issueService.findIssueAssignees(toQuery(params)); + return issueService.findIssueAssignees(issueQueryService.createFromMap(params)); } public List<Transition> listTransitions(String issueKey) { @@ -425,7 +425,7 @@ public class InternalRubyIssueService implements ServerComponent { } public IssueQuery emptyIssueQuery() { - return toQuery(Maps.<String, Object>newHashMap()); + return issueQueryService.createFromMap(Maps.<String, Object>newHashMap()); } @CheckForNull @@ -477,7 +477,7 @@ public class InternalRubyIssueService implements ServerComponent { * Execute issue filter from parameters */ public IssueFilterService.IssueFilterResult execute(Map<String, Object> props) { - return issueFilterService.execute(toQuery(props), toContext(props)); + return issueFilterService.execute(issueQueryService.createFromMap(props), toContext(props)); } /** @@ -636,35 +636,6 @@ public class InternalRubyIssueService implements ServerComponent { } @VisibleForTesting - static IssueQuery toQuery(Map<String, Object> props) { - IssueQuery.Builder builder = IssueQuery.builder() - .issueKeys(RubyUtils.toStrings(props.get(IssueFilterParameters.ISSUES))) - .severities(RubyUtils.toStrings(props.get(IssueFilterParameters.SEVERITIES))) - .statuses(RubyUtils.toStrings(props.get(IssueFilterParameters.STATUSES))) - .resolutions(RubyUtils.toStrings(props.get(IssueFilterParameters.RESOLUTIONS))) - .resolved(RubyUtils.toBoolean(props.get(IssueFilterParameters.RESOLVED))) - .components(RubyUtils.toStrings(props.get(IssueFilterParameters.COMPONENTS))) - .componentRoots(RubyUtils.toStrings(props.get(IssueFilterParameters.COMPONENT_ROOTS))) - .rules(toRules(props.get(IssueFilterParameters.RULES))) - .actionPlans(RubyUtils.toStrings(props.get(IssueFilterParameters.ACTION_PLANS))) - .reporters(RubyUtils.toStrings(props.get(IssueFilterParameters.REPORTERS))) - .assignees(RubyUtils.toStrings(props.get(IssueFilterParameters.ASSIGNEES))) - .languages(RubyUtils.toStrings(props.get(IssueFilterParameters.LANGUAGES))) - .assigned(RubyUtils.toBoolean(props.get(IssueFilterParameters.ASSIGNED))) - .planned(RubyUtils.toBoolean(props.get(IssueFilterParameters.PLANNED))) - .hideRules(RubyUtils.toBoolean(props.get(IssueFilterParameters.HIDE_RULES))) - .createdAt(RubyUtils.toDate(props.get(IssueFilterParameters.CREATED_AT))) - .createdAfter(RubyUtils.toDate(props.get(IssueFilterParameters.CREATED_AFTER))) - .createdBefore(RubyUtils.toDate(props.get(IssueFilterParameters.CREATED_BEFORE))); - String sort = (String) props.get(IssueFilterParameters.SORT); - if (!Strings.isNullOrEmpty(sort)) { - builder.sort(sort); - builder.asc(RubyUtils.toBoolean(props.get(IssueFilterParameters.ASC))); - } - return builder.build(); - } - - @VisibleForTesting static QueryContext toContext(Map<String, Object> props) { QueryContext context = new QueryContext(); Integer pageIndex = RubyUtils.toInteger(props.get(IssueFilterParameters.PAGE_INDEX)); @@ -677,27 +648,4 @@ public class InternalRubyIssueService implements ServerComponent { return context; } - @VisibleForTesting - static Collection<RuleKey> toRules(@CheckForNull Object o) { - Collection<RuleKey> result = null; - if (o != null) { - if (o instanceof List) { - // assume that it contains only strings - result = stringsToRules((List<String>) o); - } else if (o instanceof String) { - result = stringsToRules(Lists.newArrayList(Splitter.on(',').omitEmptyStrings().split((String) o))); - } - } - return result; - } - - private static Collection<RuleKey> stringsToRules(Collection<String> o) { - return Collections2.transform(o, new Function<String, RuleKey>() { - @Override - public RuleKey apply(@Nullable String s) { - return s != null ? RuleKey.parse(s) : null; - } - }); - } - } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java new file mode 100644 index 00000000000..5a335960427 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueQueryService.java @@ -0,0 +1,166 @@ +/* + * 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.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.base.Strings; +import com.google.common.collect.Iterables; +import org.sonar.api.ServerComponent; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.server.ws.Request; +import org.sonar.core.component.ComponentDto; +import org.sonar.core.persistence.DbSession; +import org.sonar.server.db.DbClient; +import org.sonar.server.issue.filter.IssueFilterParameters; +import org.sonar.server.search.ws.SearchRequestHandler; +import org.sonar.server.util.RubyUtils; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static com.google.common.collect.Lists.newArrayList; + +/** + * This component is used to create an IssueQuery, in order to transform the component and component roots keys into uuid. + */ +public class IssueQueryService implements ServerComponent { + + private final DbClient dbClient; + + public IssueQueryService(DbClient dbClient) { + this.dbClient = dbClient; + } + + public IssueQuery createFromMap(Map<String, Object> params) { + DbSession session = dbClient.openSession(false); + try { + IssueQuery.Builder builder = IssueQuery.builder() + .issueKeys(RubyUtils.toStrings(params.get(IssueFilterParameters.ISSUES))) + .severities(RubyUtils.toStrings(params.get(IssueFilterParameters.SEVERITIES))) + .statuses(RubyUtils.toStrings(params.get(IssueFilterParameters.STATUSES))) + .resolutions(RubyUtils.toStrings(params.get(IssueFilterParameters.RESOLUTIONS))) + .resolved(RubyUtils.toBoolean(params.get(IssueFilterParameters.RESOLVED))) + .components(componentUuids(session, RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENTS)))) + .componentRoots(componentUuids(session, RubyUtils.toStrings(params.get(IssueFilterParameters.COMPONENT_ROOTS)))) + .rules(toRules(params.get(IssueFilterParameters.RULES))) + .actionPlans(RubyUtils.toStrings(params.get(IssueFilterParameters.ACTION_PLANS))) + .reporters(RubyUtils.toStrings(params.get(IssueFilterParameters.REPORTERS))) + .assignees(RubyUtils.toStrings(params.get(IssueFilterParameters.ASSIGNEES))) + .languages(RubyUtils.toStrings(params.get(IssueFilterParameters.LANGUAGES))) + .assigned(RubyUtils.toBoolean(params.get(IssueFilterParameters.ASSIGNED))) + .planned(RubyUtils.toBoolean(params.get(IssueFilterParameters.PLANNED))) + .hideRules(RubyUtils.toBoolean(params.get(IssueFilterParameters.HIDE_RULES))) + .createdAt(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AT))) + .createdAfter(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_AFTER))) + .createdBefore(RubyUtils.toDate(params.get(IssueFilterParameters.CREATED_BEFORE))); + String sort = (String) params.get(IssueFilterParameters.SORT); + if (!Strings.isNullOrEmpty(sort)) { + builder.sort(sort); + builder.asc(RubyUtils.toBoolean(params.get(IssueFilterParameters.ASC))); + } + return builder.build(); + + } finally { + session.close(); + } + } + + public IssueQuery createFromRequest(Request request) { + DbSession session = dbClient.openSession(false); + try { + IssueQuery.Builder builder = IssueQuery.builder() + .issueKeys(request.paramAsStrings(IssueFilterParameters.ISSUES)) + .severities(request.paramAsStrings(IssueFilterParameters.SEVERITIES)) + .statuses(request.paramAsStrings(IssueFilterParameters.STATUSES)) + .resolutions(request.paramAsStrings(IssueFilterParameters.RESOLUTIONS)) + .resolved(request.paramAsBoolean(IssueFilterParameters.RESOLVED)) + .components(componentUuids(session, request.paramAsStrings(IssueFilterParameters.COMPONENTS))) + .componentRoots(componentUuids(session, request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOTS))) + .rules(stringsToRules(request.paramAsStrings(IssueFilterParameters.RULES))) + .actionPlans(request.paramAsStrings(IssueFilterParameters.ACTION_PLANS)) + .reporters(request.paramAsStrings(IssueFilterParameters.REPORTERS)) + .assignees(request.paramAsStrings(IssueFilterParameters.ASSIGNEES)) + .languages(request.paramAsStrings(IssueFilterParameters.LANGUAGES)) + .assigned(request.paramAsBoolean(IssueFilterParameters.ASSIGNED)) + .planned(request.paramAsBoolean(IssueFilterParameters.PLANNED)) + .createdAt(request.paramAsDateTime(IssueFilterParameters.CREATED_AT)) + .createdAfter(request.paramAsDateTime(IssueFilterParameters.CREATED_AFTER)) + .createdBefore(request.paramAsDateTime(IssueFilterParameters.CREATED_BEFORE)); + String sort = request.param(SearchRequestHandler.PARAM_SORT); + if (!Strings.isNullOrEmpty(sort)) { + builder.sort(sort); + builder.asc(request.paramAsBoolean(SearchRequestHandler.PARAM_ASCENDING)); + } + return builder.build(); + + } finally { + session.close(); + } + } + + private Collection<String> componentUuids(DbSession session, @Nullable Collection<String> componentKeys) { + Collection<String> componentUuids = newArrayList(); + if (componentKeys != null) { + for (ComponentDto component : dbClient.componentDao().getByKeys(session, componentKeys)) { + componentUuids.add(component.uuid()); + } + // If unknown components are given, if no components are set then all issues will be return, + // then we add this hack in order to return no issue in this case. + if (!componentKeys.isEmpty() && componentUuids.isEmpty()) { + componentUuids.add("<UNKNOWN>"); + } + } + return componentUuids; + } + + @VisibleForTesting + static Collection<RuleKey> toRules(@Nullable Object o) { + Collection<RuleKey> result = null; + if (o != null) { + if (o instanceof List) { + // assume that it contains only strings + result = stringsToRules((List<String>) o); + } else if (o instanceof String) { + result = stringsToRules(newArrayList(Splitter.on(',').omitEmptyStrings().split((String) o))); + } + } + return result; + } + + @CheckForNull + private static Collection<RuleKey> stringsToRules(@Nullable Collection<String> rules) { + if (rules != null) { + return newArrayList(Iterables.transform(rules, new Function<String, RuleKey>() { + @Override + public RuleKey apply(@Nullable String s) { + return s != null ? RuleKey.parse(s) : null; + } + })); + } + return null; + } +} 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 3344994ce30..e2100f8a6ad 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 @@ -130,9 +130,9 @@ public class IssueService implements ServerComponent { List<Transition> outTransitions = workflow.outTransitions(issue); List<Transition> allowedTransitions = new ArrayList<Transition>(); for (Transition transition : outTransitions) { - String projectKey = issue.projectKey(); + String projectUuid = issue.projectUuid(); if (StringUtils.isBlank(transition.requiredProjectPermission()) || - (projectKey != null && UserSession.get().hasProjectPermission(transition.requiredProjectPermission(), projectKey))) { + (projectUuid != null && UserSession.get().hasProjectPermissionByUuid(transition.requiredProjectPermission(), projectUuid))) { allowedTransitions.add(transition); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueStorage.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueStorage.java index a261dd3e888..f10ef8d5c73 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueStorage.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ServerIssueStorage.java @@ -22,6 +22,7 @@ package org.sonar.server.issue; import org.sonar.api.ServerComponent; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.rules.RuleFinder; +import org.sonar.core.component.ComponentDto; import org.sonar.core.issue.db.IssueDto; import org.sonar.core.issue.db.IssueStorage; import org.sonar.core.persistence.DbSession; @@ -44,26 +45,26 @@ public class ServerIssueStorage extends IssueStorage implements ServerComponent @Override protected void doInsert(DbSession session, Date now, DefaultIssue issue) { - long componentId = componentId(session, issue); - long projectId = projectId(session, issue); + ComponentDto component = component(session, issue); + ComponentDto project = project(session, issue); int ruleId = ruleId(issue); - IssueDto dto = IssueDto.toDtoForInsert(issue, componentId, projectId, ruleId, now); + IssueDto dto = IssueDto.toDtoForServerInsert(issue, component, project, ruleId, now); dbClient.issueDao().insert(session, dto); } @Override protected void doUpdate(DbSession session, Date now, DefaultIssue issue) { - IssueDto dto = IssueDto.toDtoForUpdate(issue, projectId(session, issue), now); + IssueDto dto = IssueDto.toDtoForUpdate(issue, project(session, issue).getId(), now); dbClient.issueDao().update(session, dto); } - protected long componentId(DbSession session, DefaultIssue issue) { - return dbClient.componentDao().getAuthorizedComponentByKey(issue.componentKey(), session).getId(); + protected ComponentDto component(DbSession session, DefaultIssue issue) { + return dbClient.componentDao().getByKey(session, issue.componentKey()); } - protected long projectId(DbSession session, DefaultIssue issue) { - return dbClient.componentDao().getAuthorizedComponentByKey(issue.projectKey(), session).getId(); + protected ComponentDto project(DbSession session, DefaultIssue issue) { + return dbClient.componentDao().getByKey(session, issue.projectKey()); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/db/IssueAuthorizationDao.java b/server/sonar-server/src/main/java/org/sonar/server/issue/db/IssueAuthorizationDao.java index 918ce814ddb..c375f650eb6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/db/IssueAuthorizationDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/db/IssueAuthorizationDao.java @@ -41,7 +41,7 @@ import java.util.Map; public class IssueAuthorizationDao extends BaseDao<IssueAuthorizationMapper, IssueAuthorizationDto, String> implements DaoComponent { - public static final String PROJECT_KEY = "project"; + public static final String PROJECT_UUID = "project"; public IssueAuthorizationDao() { this(System2.INSTANCE); @@ -72,7 +72,7 @@ public class IssueAuthorizationDao extends BaseDao<IssueAuthorizationMapper, Iss IssueAuthorizationDto issueAuthorizationDto = authorizationDtoMap.get(project); if (issueAuthorizationDto == null) { issueAuthorizationDto = new IssueAuthorizationDto() - .setProject(project) + .setProjectUuid(project) .setPermission(UserRole.USER); issueAuthorizationDto.setUpdatedAt(updatedAt); } @@ -87,9 +87,9 @@ public class IssueAuthorizationDao extends BaseDao<IssueAuthorizationMapper, Iss @Override public void enqueueCollected() { - String projectKey = getParams().get("project"); - if (authorizationDtoMap.isEmpty() && projectKey != null) { - getSession().enqueue(new DeleteKey<String>(getIndexType(), projectKey)); + String projectUuid = getParams().get("project"); + if (authorizationDtoMap.isEmpty() && projectUuid != null) { + getSession().enqueue(new DeleteKey<String>(getIndexType(), projectUuid)); } else { for (IssueAuthorizationDto authorization : authorizationDtoMap.values()) { getSession().enqueue(new UpsertDto<IssueAuthorizationDto>(getIndexType(), authorization, true)); @@ -104,7 +104,7 @@ public class IssueAuthorizationDao extends BaseDao<IssueAuthorizationMapper, Iss Map<String, Object> finalParams = super.getSynchronizationParams(date, params); finalParams.put("permission", UserRole.USER); finalParams.put("anyone", DefaultGroups.ANYONE); - finalParams.put(PROJECT_KEY, params.get(PROJECT_KEY)); + finalParams.put(PROJECT_UUID, params.get(PROJECT_UUID)); return finalParams; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/db/IssueDao.java b/server/sonar-server/src/main/java/org/sonar/server/issue/db/IssueDao.java index bd38edb6da7..f9fda73d3d1 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/db/IssueDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/db/IssueDao.java @@ -83,6 +83,7 @@ public class IssueDao extends BaseDao<IssueMapper, IssueDto, String> implements @Override protected Map<String, Object> getSynchronizationParams(Date date, Map<String, String> params) { Map<String, Object> finalParams = super.getSynchronizationParams(date, params); + // TODO replace usage of project key by project uuid finalParams.put(PROJECT_KEY, params.get(PROJECT_KEY)); return finalParams; } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationNormalizer.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationNormalizer.java index 5ee7c4d07ad..53ccd57ca18 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationNormalizer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueAuthorizationNormalizer.java @@ -20,6 +20,7 @@ package org.sonar.server.issue.index; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import org.elasticsearch.action.update.UpdateRequest; import org.sonar.core.issue.db.IssueAuthorizationDto; @@ -29,11 +30,7 @@ import org.sonar.server.search.IndexField; import org.sonar.server.search.Indexable; import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class IssueAuthorizationNormalizer extends BaseNormalizer<IssueAuthorizationDto, String> { @@ -70,7 +67,9 @@ public class IssueAuthorizationNormalizer extends BaseNormalizer<IssueAuthorizat public List<UpdateRequest> normalize(IssueAuthorizationDto dto) { Map<String, Object> update = new HashMap<String, Object>(); - update.put(IssueAuthorizationField.PROJECT.field(), dto.getProject()); + Preconditions.checkNotNull(dto.getProjectUuid(), "Project uuid is null"); + + update.put(IssueAuthorizationField.PROJECT.field(), dto.getProjectUuid()); update.put(IssueAuthorizationField.PERMISSION.field(), dto.getPermission()); update.put(IssueAuthorizationField.USERS.field(), dto.getUsers()); update.put(IssueAuthorizationField.GROUPS.field(), dto.getGroups()); diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java index 89f67c62988..6344ad33d12 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueDoc.java @@ -28,6 +28,7 @@ import org.sonar.server.search.BaseDoc; import org.sonar.server.search.IndexUtils; import javax.annotation.CheckForNull; + import java.util.Collections; import java.util.Date; import java.util.List; @@ -46,10 +47,25 @@ public class IssueDoc extends BaseDoc implements Issue { @Override public String componentKey() { + throw new IllegalStateException("componentKey is not available on server side"); + } + + @Override + public String componentUuid() { return getField(IssueNormalizer.IssueField.COMPONENT.field()); } @Override + public String projectKey() { + throw new IllegalStateException("projectKey is not available on server side"); + } + + @Override + public String projectUuid() { + return getField(IssueNormalizer.IssueField.PROJECT.field()); + } + + @Override public RuleKey ruleKey() { return RuleKey.parse((String) getField(IssueNormalizer.IssueField.RULE_KEY.field())); } @@ -158,7 +174,7 @@ public class IssueDoc extends BaseDoc implements Issue { @Override public boolean isNew() { - throw new IllegalStateException("Only available for batch"); + throw new IllegalStateException("isNew is only available for batch"); } @Override @@ -167,9 +183,4 @@ public class IssueDoc extends BaseDoc implements Issue { Integer debt = getNullableField(IssueNormalizer.IssueField.DEBT.field()); return (debt != null) ? Duration.create(Long.valueOf(debt)) : null; } - - @Override - public String projectKey() { - return getField(IssueNormalizer.IssueField.PROJECT.field()); - } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java index c7bd430934e..f12875c331e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -246,7 +246,7 @@ public class IssueIndex extends BaseIndex<Issue, IssueDto, String> { filters.put(IssueNormalizer.IssueField.KEY.field(), matchFilter(IssueNormalizer.IssueField.KEY, query.issueKeys())); filters.put(IssueNormalizer.IssueField.ACTION_PLAN.field(), matchFilter(IssueNormalizer.IssueField.ACTION_PLAN, query.actionPlans())); filters.put(IssueNormalizer.IssueField.ASSIGNEE.field(), matchFilter(IssueNormalizer.IssueField.ASSIGNEE, query.assignees())); - filters.put(IssueNormalizer.IssueField.PROJECT.field(), matchFilter(IssueNormalizer.IssueField.PROJECT, query.componentRoots())); + filters.put(IssueNormalizer.IssueField.MODULE_PATH.field(), matchFilter(IssueNormalizer.IssueField.MODULE_PATH, query.componentRoots())); filters.put(IssueNormalizer.IssueField.COMPONENT.field(), matchFilter(IssueNormalizer.IssueField.COMPONENT, query.components())); filters.put(IssueNormalizer.IssueField.LANGUAGE.field(), matchFilter(IssueNormalizer.IssueField.LANGUAGE, query.languages())); filters.put(IssueNormalizer.IssueField.RESOLUTION.field(), matchFilter(IssueNormalizer.IssueField.RESOLUTION, query.resolutions())); @@ -276,7 +276,7 @@ public class IssueIndex extends BaseIndex<Issue, IssueDto, String> { FilterBuilders.boolFilter() .must(FilterBuilders.termFilter(IssueAuthorizationNormalizer.IssueAuthorizationField.PERMISSION.field(), UserRole.USER), groupsAndUser) .cache(true)) - ); + ); } private void addDatesFilter(Map<String, FilterBuilder> filters, IssueQuery query) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java index 0db925b3e18..8a5134e0537 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueNormalizer.java @@ -19,6 +19,7 @@ */ package org.sonar.server.issue.index; +import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import org.elasticsearch.action.update.UpdateRequest; import org.sonar.api.rule.Severity; @@ -68,6 +69,7 @@ public class IssueNormalizer extends BaseNormalizer<IssueDto, String> { public static final IndexField SEVERITY_VALUE = addSortable(IndexField.Type.NUMERIC, "severityValue"); public static final IndexField LANGUAGE = add(IndexField.Type.STRING, "language"); public static final IndexField RULE_KEY = add(IndexField.Type.STRING, "ruleKey"); + public static final IndexField MODULE_PATH = add(IndexField.Type.UUID_PATH, "modulePath"); public static final Set<IndexField> ALL_FIELDS = getAllFields(); @@ -90,7 +92,10 @@ public class IssueNormalizer extends BaseNormalizer<IssueDto, String> { public List<UpdateRequest> normalize(IssueDto dto) { Map<String, Object> update = newHashMap(); - update.put("_parent", dto.getRootComponentKey()); + Preconditions.checkNotNull(dto.getProjectUuid(), "Project uuid is null on issue %s", dto.getKey()); +// Preconditions.checkNotNull(dto.getComponentUuid(), "Component uuid is null on issue %s", dto.getKey()); + + update.put("_parent", dto.getProjectUuid()); update.put(IssueField.KEY.field(), dto.getKey()); update.put(IssueField.UPDATED_AT.field(), dto.getUpdatedAt()); update.put(IssueField.CREATED_AT.field(), dto.getCreatedAt()); @@ -100,8 +105,9 @@ public class IssueNormalizer extends BaseNormalizer<IssueDto, String> { update.put(IssueField.ASSIGNEE.field(), dto.getAssignee()); update.put(IssueField.AUTHOR_LOGIN.field(), dto.getAuthorLogin()); update.put(IssueField.ISSUE_CLOSE_DATE.field(), dto.getIssueCloseDate()); - update.put(IssueField.PROJECT.field(), dto.getRootComponentKey()); - update.put(IssueField.COMPONENT.field(), dto.getComponentKey()); + update.put(IssueField.PROJECT.field(), dto.getProjectUuid()); + update.put(IssueField.MODULE_PATH.field(), dto.getModuleUuidPath()); + update.put(IssueField.COMPONENT.field(), dto.getComponentUuid()); update.put(IssueField.ISSUE_CREATED_AT.field(), dto.getIssueCreationDate()); update.put(IssueField.ISSUE_UPDATED_AT.field(), dto.getIssueUpdateDate()); update.put(IssueField.EFFORT.field(), dto.getEffortToFix()); @@ -123,8 +129,8 @@ public class IssueNormalizer extends BaseNormalizer<IssueDto, String> { return ImmutableList.of( new UpdateRequest() .id(dto.getKey()) - .routing(dto.getRootComponentKey()) - .parent(dto.getRootComponentKey()) + .routing(dto.getProjectUuid()) + .parent(dto.getProjectUuid()) .doc(update) .upsert(upsert)); } 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 23a2c1093d8..4a87b347eb2 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 @@ -73,8 +73,8 @@ public class IssueActionsWriter implements ServerComponent { actions.add("assign_to_me"); } actions.add("plan"); - String projectKey = issue.projectKey(); - if (projectKey != null && UserSession.get().hasProjectPermission(UserRole.ISSUE_ADMIN, projectKey)) { + String projectUuid = issue.projectUuid(); + if (projectUuid != null && UserSession.get().hasProjectPermissionByUuid(UserRole.ISSUE_ADMIN, projectUuid)) { actions.add("set_severity"); } for (Action action : actionService.listAvailableActions(issue)) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowAction.java index 65b4998706a..1480ff0de01 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssueShowAction.java @@ -166,22 +166,22 @@ public class IssueShowAction implements RequestHandler { } private void addComponents(DbSession session, Issue issue, JsonWriter json) { - // component, module and project can be null if they were removed - ComponentDto component = dbClient.componentDao().getNullableByKey(session, issue.componentKey()); - Long subProjectId = component != null ? component.subProjectId() : null; + ComponentDto component = dbClient.componentDao().getByUuid(session, issue.componentUuid()); + Long subProjectId = component.subProjectId(); ComponentDto subProject = subProjectId != null ? dbClient.componentDao().getNullableById(subProjectId, session) : null; - ComponentDto project = component != null ? dbClient.componentDao().getNullableById(component.projectId(), session) : null; + ComponentDto project = dbClient.componentDao().getByUuid(session, component.projectUuid()); - String projectName = project != null ? project.longName() != null ? project.longName() : project.name() : null; + String projectName = project.longName() != null ? project.longName() : project.name(); // Do not display sub project long name if sub project and project are the same - boolean displaySubProjectLongName = subProject != null && project != null && !subProject.getId().equals(project.getId()); + boolean displaySubProjectLongName = subProject != null && !subProject.getId().equals(project.getId()); String subProjectName = displaySubProjectLongName ? subProject.longName() != null ? subProject.longName() : subProject.name() : null; json - .prop("component", issue.componentKey()) - .prop("componentLongName", component != null ? component.longName() : null) - .prop("componentQualifier", component != null ? component.qualifier() : null) - .prop("project", issue.projectKey()) + .prop("component", component.key()) + .prop("componentLongName", component.longName()) + .prop("componentQualifier", component.qualifier()) + .prop("componentEnabled", component.isEnabled()) + .prop("project", project.key()) .prop("projectName", projectName) .prop("subProjectName", subProjectName); } 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 ba2f458ba52..b59b2debab3 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 @@ -19,8 +19,7 @@ */ package org.sonar.server.issue.ws; -import com.google.common.base.Function; -import com.google.common.base.Strings; +import com.google.common.base.Predicate; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Iterables; import com.google.common.collect.Multimap; @@ -46,9 +45,11 @@ import org.sonar.core.persistence.DbSession; import org.sonar.markdown.Markdown; import org.sonar.server.db.DbClient; import org.sonar.server.issue.IssueQuery; +import org.sonar.server.issue.IssueQueryService; import org.sonar.server.issue.IssueService; import org.sonar.server.issue.actionplan.ActionPlanService; import org.sonar.server.issue.filter.IssueFilterParameters; +import org.sonar.server.issue.index.IssueDoc; import org.sonar.server.rule.Rule; import org.sonar.server.rule.RuleService; import org.sonar.server.search.QueryContext; @@ -83,6 +84,7 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { private final IssueService service; private final IssueActionsWriter actionsWriter; + private final IssueQueryService issueQueryService; private final RuleService ruleService; private final DbClient dbClient; private final ActionPlanService actionPlanService; @@ -92,13 +94,14 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { private final SourceService sourceService; private final ScmWriter scmWriter; - public SearchAction(DbClient dbClient, IssueChangeDao issueChangeDao, IssueService service, IssueActionsWriter actionsWriter, RuleService ruleService, - ActionPlanService actionPlanService, UserFinder userFinder, I18n i18n, Durations durations, SourceService sourceService, ScmWriter scmWriter) { + public SearchAction(DbClient dbClient, IssueChangeDao issueChangeDao, IssueService service, IssueActionsWriter actionsWriter, IssueQueryService issueQueryService, + RuleService ruleService, ActionPlanService actionPlanService, UserFinder userFinder, I18n i18n, Durations durations, SourceService sourceService, ScmWriter scmWriter) { super(SEARCH_ACTION); this.dbClient = dbClient; this.issueChangeDao = issueChangeDao; this.service = service; this.actionsWriter = actionsWriter; + this.issueQueryService = issueQueryService; this.ruleService = ruleService; this.actionPlanService = actionPlanService; this.userFinder = userFinder; @@ -194,30 +197,7 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { @Override protected IssueQuery doQuery(Request request) { - IssueQuery.Builder builder = IssueQuery.builder() - .issueKeys(request.paramAsStrings(IssueFilterParameters.ISSUES)) - .severities(request.paramAsStrings(IssueFilterParameters.SEVERITIES)) - .statuses(request.paramAsStrings(IssueFilterParameters.STATUSES)) - .resolutions(request.paramAsStrings(IssueFilterParameters.RESOLUTIONS)) - .resolved(request.paramAsBoolean(IssueFilterParameters.RESOLVED)) - .components(request.paramAsStrings(IssueFilterParameters.COMPONENTS)) - .componentRoots(request.paramAsStrings(IssueFilterParameters.COMPONENT_ROOTS)) - .rules(stringsToRules(request.paramAsStrings(IssueFilterParameters.RULES))) - .actionPlans(request.paramAsStrings(IssueFilterParameters.ACTION_PLANS)) - .reporters(request.paramAsStrings(IssueFilterParameters.REPORTERS)) - .assignees(request.paramAsStrings(IssueFilterParameters.ASSIGNEES)) - .languages(request.paramAsStrings(IssueFilterParameters.LANGUAGES)) - .assigned(request.paramAsBoolean(IssueFilterParameters.ASSIGNED)) - .planned(request.paramAsBoolean(IssueFilterParameters.PLANNED)) - .createdAt(request.paramAsDateTime(IssueFilterParameters.CREATED_AT)) - .createdAfter(request.paramAsDateTime(IssueFilterParameters.CREATED_AFTER)) - .createdBefore(request.paramAsDateTime(IssueFilterParameters.CREATED_BEFORE)); - String sort = request.param(SearchRequestHandler.PARAM_SORT); - if (!Strings.isNullOrEmpty(sort)) { - builder.sort(sort); - builder.asc(request.paramAsBoolean(SearchRequestHandler.PARAM_ASCENDING)); - } - return builder.build(); + return issueQueryService.createFromRequest(request); } @Override @@ -239,19 +219,22 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { protected void doContextResponse(Request request, QueryContext context, Result<Issue> result, JsonWriter json) { List<String> issueKeys = newArrayList(); Set<RuleKey> ruleKeys = newHashSet(); - Set<String> projectKeys = newHashSet(); - Set<String> componentKeys = newHashSet(); + Set<String> projectUuids = newHashSet(); + Set<String> componentUuids = newHashSet(); Set<String> actionPlanKeys = newHashSet(); List<String> userLogins = newArrayList(); Map<String, User> usersByLogin = newHashMap(); - Map<String, ComponentDto> componentsByKey = newHashMap(); + Map<String, ComponentDto> componentsByUuid = newHashMap(); Multimap<String, DefaultIssueComment> commentsByIssues = ArrayListMultimap.create(); + Collection<ComponentDto> componentDtos = newHashSet(); + List<ComponentDto> projectDtos = newArrayList(); for (Issue issue : result.getHits()) { + IssueDoc issueDoc = (IssueDoc) issue; issueKeys.add(issue.key()); ruleKeys.add(issue.ruleKey()); - projectKeys.add(issue.projectKey()); - componentKeys.add(issue.componentKey()); + projectUuids.add(issueDoc.projectUuid()); + componentUuids.add(issueDoc.componentUuid()); actionPlanKeys.add(issue.actionPlanKey()); if (issue.reporter() != null) { userLogins.add(issue.reporter()); @@ -270,14 +253,15 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { } usersByLogin = getUsersByLogin(userLogins); - List<ComponentDto> componentDtos = dbClient.componentDao().getByKeys(session, componentKeys); - List<ComponentDto> subProjectDtos = dbClient.componentDao().findSubProjectsByComponentKeys(session, componentKeys); - List<ComponentDto> projectDtos = dbClient.componentDao().getByKeys(session, projectKeys); + List<ComponentDto> fileDtos = dbClient.componentDao().getByUuids(session, componentUuids); + List<ComponentDto> subProjectDtos = dbClient.componentDao().findSubProjectsByComponentUuids(session, componentUuids); + projectDtos = dbClient.componentDao().getByUuids(session, projectUuids); + componentDtos.addAll(fileDtos); componentDtos.addAll(subProjectDtos); componentDtos.addAll(projectDtos); for (ComponentDto componentDto : componentDtos) { - componentsByKey.put(componentDto.key(), componentDto); + componentsByUuid.put(componentDto.uuid(), componentDto); } writeProjects(json, projectDtos); writeComponents(json, componentDtos); @@ -287,7 +271,8 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { Map<String, ActionPlan> actionPlanByKeys = getActionPlanByKeys(actionPlanKeys); - writeIssues(result, commentsByIssues, usersByLogin, actionPlanByKeys, componentsByKey, request.paramAsStrings(EXTRA_FIELDS_PARAM), json); + writeIssues(result, commentsByIssues, usersByLogin, actionPlanByKeys, componentsByUuid, getProjectsByComponentUuid(componentDtos, projectDtos), + request.paramAsStrings(EXTRA_FIELDS_PARAM), json); writeRules(json, !request.mandatoryParamAsBoolean(IssueFilterParameters.HIDE_RULES) ? ruleService.getByKeys(ruleKeys) : Collections.<Rule>emptyList()); writeUsers(json, usersByLogin); writeActionPlans(json, actionPlanByKeys.values()); @@ -333,23 +318,24 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { } private void writeIssues(Result<Issue> result, Multimap<String, DefaultIssueComment> commentsByIssues, Map<String, User> usersByLogin, Map<String, ActionPlan> actionPlanByKeys, - Map<String, ComponentDto> componentsByKey, @Nullable List<String> extraFields, JsonWriter json) { + Map<String, ComponentDto> componentsByUuid, Map<String, ComponentDto> projectsByComponentUuid, @Nullable List<String> extraFields, JsonWriter json) { json.name("issues").beginArray(); for (Issue issue : result.getHits()) { json.beginObject(); String actionPlanKey = issue.actionPlanKey(); - ComponentDto componentDto = componentsByKey.get(issue.componentKey()); + ComponentDto file = componentsByUuid.get(((IssueDoc) issue).componentUuid()); + ComponentDto project = file != null ? projectsByComponentUuid.get(file.uuid()) : null; Duration debt = issue.debt(); Date updateDate = issue.updateDate(); json .prop("key", issue.key()) - .prop("component", issue.componentKey()) + .prop("component", file != null ? file.getKey() : null) // Only used for the compatibility with the Issues Java WS Client <= 4.4 used by Eclipse - .prop("componentId", componentDto != null ? componentDto.getId() : null) - .prop("project", issue.projectKey()) + .prop("componentId", file != null ? file.getId() : null) + .prop("project", project != null ? project.getKey() : null) .prop("rule", issue.ruleKey().toString()) .prop("status", issue.status()) .prop("resolution", issue.resolution()) @@ -367,32 +353,32 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { .prop("fUpdateAge", formatAgeDate(updateDate)) .prop("closeDate", isoDate(issue.closeDate())); - writeIssueSnippet(issue, json); + writeIssueSnippet(issue, file, json); writeIssueComments(commentsByIssues.get(issue.key()), usersByLogin, json); writeIssueAttributes(issue, json); - writeIssueExtraFields(issue, usersByLogin, actionPlanByKeys, extraFields, json); + writeIssueExtraFields(issue, project != null ? project.getKey() : null, usersByLogin, actionPlanByKeys, extraFields, json); json.endObject(); } json.endArray(); } - private void writeIssueSnippet(Issue issue, JsonWriter json) { + private void writeIssueSnippet(Issue issue, @Nullable ComponentDto file, JsonWriter json) { Integer lineNumber = issue.line(); - if (lineNumber == null) { + if (lineNumber == null || file == null) { return; } - String componentKey = issue.componentKey(); + String componentKey = file.key(); int from = Math.max(lineNumber - 1, 1); int to = from + 2; int lineCounter = from; List<String> lines = sourceService.getLinesAsHtml(componentKey, from, to); if (lines != null) { json.name("sources").beginArray(); - for(String line: lines) { + for (String line : lines) { json.beginArray().value(lineCounter).value(line).endArray(); - lineCounter ++; + lineCounter++; } json.endArray(); String scmAuthorData = sourceService.getScmAuthorData(componentKey); @@ -432,7 +418,9 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { } } - private void writeIssueExtraFields(Issue issue, Map<String, User> usersByLogin, Map<String, ActionPlan> actionPlanByKeys, @Nullable List<String> extraFields, JsonWriter json) { + private void writeIssueExtraFields(Issue issue, @Nullable String projectKey, Map<String, User> usersByLogin, Map<String, ActionPlan> actionPlanByKeys, + @Nullable List<String> extraFields, + JsonWriter json) { if (extraFields != null && UserSession.get().isLoggedIn()) { if (extraFields.contains(ACTIONS_EXTRA_FIELD)) { actionsWriter.writeActions(issue, json); @@ -462,12 +450,14 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { } } - private void writeComponents(JsonWriter json, List<ComponentDto> components) { + private void writeComponents(JsonWriter json, Collection<ComponentDto> components) { json.name("components").beginArray(); for (ComponentDto component : components) { json.beginObject() + .prop("uuid", component.uuid()) .prop("key", component.key()) .prop("id", component.getId()) + .prop("enabled", component.isEnabled()) .prop("qualifier", component.qualifier()) .prop("name", component.name()) .prop("longName", component.longName()) @@ -484,6 +474,7 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { json.name("projects").beginArray(); for (ComponentDto project : projects) { json.beginObject() + .prop("uuid", project.uuid()) .prop("key", project.key()) .prop("id", project.getId()) .prop("qualifier", project.qualifier()) @@ -548,6 +539,19 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { return actionPlans; } + private Map<String, ComponentDto> getProjectsByComponentUuid(Collection<ComponentDto> components, Collection<ComponentDto> projects) { + Map<String, ComponentDto> projectsByComponentUuid = newHashMap(); + for (final ComponentDto component : components) { + projectsByComponentUuid.put(component.uuid(), Iterables.find(projects, new Predicate<ComponentDto>() { + @Override + public boolean apply(@Nullable ComponentDto input) { + return input != null && input.uuid().equals(component.projectUuid()); + } + })); + } + return projectsByComponentUuid; + } + @CheckForNull private String isoDate(@Nullable Date date) { if (date != null) { @@ -572,16 +576,4 @@ public class SearchAction extends SearchRequestHandler<IssueQuery, Issue> { return null; } - @CheckForNull - private static Collection<RuleKey> stringsToRules(@Nullable Collection<String> rules) { - if (rules != null) { - return newArrayList(Iterables.transform(rules, new Function<String, RuleKey>() { - @Override - public RuleKey apply(@Nullable String s) { - return s != null ? RuleKey.parse(s) : null; - } - })); - } - return null; - } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/InternalPermissionService.java b/server/sonar-server/src/main/java/org/sonar/server/permission/InternalPermissionService.java index 9ef6274b638..eda3b0b66af 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/InternalPermissionService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/InternalPermissionService.java @@ -149,7 +149,7 @@ public class InternalPermissionService implements ServerComponent { for (String componentKey : query.getSelectedComponents()) { AuthorizedComponentDto component = dbClient.componentDao().getAuthorizedComponentByKey(componentKey, session); permissionFacade.applyPermissionTemplate(session, query.getTemplateKey(), component.getId()); - synchronizePermissions(session, componentKey); + synchronizePermissions(session, component.uuid()); } session.commit(); } finally { @@ -176,7 +176,7 @@ public class InternalPermissionService implements ServerComponent { if (changed) { String project = permissionChangeQuery.component(); if (project != null) { - synchronizePermissions(session, project); + synchronizePermissions(session, dbClient.componentDao().getAuthorizedComponentByKey(project, session).uuid()); } session.commit(); } @@ -275,9 +275,9 @@ public class InternalPermissionService implements ServerComponent { } } - public void synchronizePermissions(DbSession session, String projectKey) { + public void synchronizePermissions(DbSession session, String projectUuid) { dbClient.issueAuthorizationDao().synchronizeAfter(session, index.get(IssueAuthorizationIndex.class).getLastSynchronization(), - ImmutableMap.of(IssueAuthorizationDao.PROJECT_KEY, projectKey)); + ImmutableMap.of(IssueAuthorizationDao.PROJECT_UUID, projectUuid)); } } 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 87001f174ec..dd8b3a9877d 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 @@ -502,6 +502,7 @@ class ServerComponents { pico.addSingleton(org.sonar.server.issue.ws.SearchAction.class); pico.addSingleton(IssueService.class); pico.addSingleton(IssueActionsWriter.class); + pico.addSingleton(IssueQueryService.class); // issue filters pico.addSingleton(IssueFilterService.class); diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java b/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java index 89a8b886ab8..4f48332325b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/search/BaseIndex.java @@ -270,11 +270,20 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial return mapDateField(field); } else if (field.type() == IndexField.Type.NUMERIC) { return mapNumericField(field); + } else if (field.type() == IndexField.Type.UUID_PATH) { + return mapUuidPathField(field); } else { throw new IllegalStateException("Mapping does not exist for type: " + field.type()); } } + private Map mapUuidPathField(IndexField field) { + return ImmutableMap.of( + "type", "string", + "index", "analyzed", + "analyzer", "uuid_analyzer"); + } + protected Map mapNumericField(IndexField field) { return ImmutableMap.of("type", "double"); } @@ -572,7 +581,14 @@ public abstract class BaseIndex<DOMAIN, DTO extends Dto<KEY>, KEY extends Serial // Path Analyzer .put("index.analysis.analyzer.path_analyzer.type", "custom") - .put("index.analysis.analyzer.path_analyzer.tokenizer", "path_hierarchy"); + .put("index.analysis.analyzer.path_analyzer.tokenizer", "path_hierarchy") + + // UUID Module analyzer + .put("index.analysis.tokenizer.dot_tokenizer.type", "pattern") + .put("index.analysis.tokenizer.dot_tokenizer.pattern", "\\.") + .put("index.analysis.analyzer.uuid_analyzer.type", "custom") + .putArray("index.analysis.analyzer.uuid_analyzer.filter", "trim", "lowercase") + .put("index.analysis.analyzer.uuid_analyzer.tokenizer", "dot_tokenizer"); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/IndexField.java b/server/sonar-server/src/main/java/org/sonar/server/search/IndexField.java index 73926394d6e..5a271bfa061 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/search/IndexField.java +++ b/server/sonar-server/src/main/java/org/sonar/server/search/IndexField.java @@ -28,7 +28,7 @@ import java.util.Collections; public class IndexField { public static enum Type { - STRING, TEXT, DATE, BOOLEAN, NUMERIC, OBJECT + STRING, TEXT, DATE, BOOLEAN, NUMERIC, OBJECT, UUID_PATH } public static final String SORT_SUFFIX = "sort"; diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/IndexQueue.java b/server/sonar-server/src/main/java/org/sonar/server/search/IndexQueue.java index ae3548f34ea..a7fb911ad3f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/search/IndexQueue.java +++ b/server/sonar-server/src/main/java/org/sonar/server/search/IndexQueue.java @@ -60,46 +60,41 @@ public class IndexQueue implements ServerComponent, WorkQueue<IndexAction<?>> { if (actions.isEmpty()) { return; } - try { - - boolean refreshRequired = false; - - Map<String, Index> indexes = getIndexMap(); - Set<String> indices = new HashSet<String>(); - for (IndexAction action : actions) { - Index index = indexes.get(action.getIndexType()); - action.setIndex(index); - if (action.needsRefresh()) { - refreshRequired = true; - indices.add(index.getIndexName()); - } + boolean refreshRequired = false; + + Map<String, Index> indexes = getIndexMap(); + Set<String> indices = new HashSet<String>(); + for (IndexAction action : actions) { + Index index = indexes.get(action.getIndexType()); + action.setIndex(index); + if (action.needsRefresh()) { + refreshRequired = true; + indices.add(index.getIndexName()); } + } - BulkRequestBuilder bulkRequestBuilder = new BulkRequestBuilder(searchClient); + BulkRequestBuilder bulkRequestBuilder = new BulkRequestBuilder(searchClient); - long normTime = processActionsIntoQueries(bulkRequestBuilder, actions); + long normTime = processActionsIntoQueries(bulkRequestBuilder, actions); - if (bulkRequestBuilder.numberOfActions() > 0) { - // execute the request - long indexTime = System.currentTimeMillis(); - BulkResponse response = searchClient.execute(bulkRequestBuilder.setRefresh(false)); + if (bulkRequestBuilder.numberOfActions() > 0) { + // execute the request + long indexTime = System.currentTimeMillis(); + BulkResponse response = searchClient.execute(bulkRequestBuilder.setRefresh(false)); - indexTime = System.currentTimeMillis() - indexTime; + indexTime = System.currentTimeMillis() - indexTime; - long refreshTime = 0; - if (refreshRequired) { - refreshTime = this.refreshRequiredIndex(indices); - } + long refreshTime = 0; + if (refreshRequired) { + refreshTime = this.refreshRequiredIndex(indices); + } - LOGGER.debug("-- submitted {} items with {}ms in normalization, {}ms indexing and {}ms refresh({}). Total: {}ms", - bulkRequestBuilder.numberOfActions(), normTime, indexTime, refreshTime, indices, (normTime + indexTime + refreshTime)); + LOGGER.debug("-- submitted {} items with {}ms in normalization, {}ms indexing and {}ms refresh({}). Total: {}ms", + bulkRequestBuilder.numberOfActions(), normTime, indexTime, refreshTime, indices, (normTime + indexTime + refreshTime)); - if (response.hasFailures()) { - throw new IllegalStateException("Errors while indexing stack: " + response.buildFailureMessage()); - } + if (response.hasFailures()) { + throw new IllegalStateException("Errors while indexing stack: " + response.buildFailureMessage()); } - } catch (Exception e) { - LOGGER.error("Could not commit to ElasticSearch", e); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java b/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java index 98622a74b60..cdaf45cc962 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/UserSession.java @@ -61,6 +61,7 @@ public class UserSession { List<String> globalPermissions = null; HashMultimap<String, String> projectKeyByPermission = HashMultimap.create(); + HashMultimap<String, String> projectUuidByPermission = HashMultimap.create(); Map<String, String> projectKeyByComponentKey = newHashMap(); List<String> projectPermissions = newArrayList(); @@ -186,6 +187,21 @@ public class UserSession { return projectKeyByPermission.get(permission).contains(projectKey); } + + /** + * Does the user have the given project permission ? + */ + public boolean hasProjectPermissionByUuid(String permission, String projectUuid) { + if (!projectPermissions.contains(permission)) { + Collection<String> projectUuids = authorizationDao().selectAuthorizedRootProjectsUuids(userId, permission); + for (String key : projectUuids) { + projectUuidByPermission.put(permission, key); + } + projectPermissions.add(permission); + } + return projectUuidByPermission.get(permission).contains(projectUuid); + } + /** * Ensures that user implies the specified project permission on a component. If not a {@link org.sonar.server.exceptions.ForbiddenException} is thrown. */ diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentCleanerServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentCleanerServiceMediumTest.java index b42ae6127e5..5b2f5fce325 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentCleanerServiceMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentCleanerServiceMediumTest.java @@ -24,8 +24,6 @@ import org.junit.After; import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Scopes; import org.sonar.api.security.DefaultGroups; import org.sonar.api.web.UserRole; import org.sonar.core.component.ComponentDto; @@ -65,12 +63,7 @@ public class ComponentCleanerServiceMediumTest { @Test public void delete_project() throws Exception { - ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("MyProject") - .setScope(Scopes.PROJECT) - .setQualifier(Qualifiers.PROJECT) - .setProjectId_unit_test_only(1L); + ComponentDto project = ComponentTesting.newProjectDto(); db.componentDao().insert(session, project); session.commit(); @@ -81,12 +74,7 @@ public class ComponentCleanerServiceMediumTest { @Test public void remove_issue_permission_index_when_deleting_a_project() throws Exception { - ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("MyProject") - .setScope(Scopes.PROJECT) - .setQualifier(Qualifiers.PROJECT) - .setProjectId_unit_test_only(1L); + ComponentDto project = ComponentTesting.newProjectDto(); db.componentDao().insert(session, project); // project can be seen by anyone @@ -95,24 +83,20 @@ public class ComponentCleanerServiceMediumTest { session.commit(); - assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNotNull(); + assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.uuid())).isNotNull(); service.delete(project.getKey()); - assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNull(); + assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.uuid())).isNull(); } @Test(expected = IllegalArgumentException.class) public void fail_to_delete_not_project() throws Exception { - ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("MyProject") - .setScope(Scopes.DIRECTORY) - .setQualifier(Qualifiers.DIRECTORY) - .setProjectId_unit_test_only(1L); - db.componentDao().insert(session, project); + ComponentDto project = ComponentTesting.newProjectDto(); + ComponentDto file = ComponentTesting.newFileDto(project); + db.componentDao().insert(session, project, file); session.commit(); - service.delete(project.getKey()); + service.delete(file.getKey()); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceMediumTest.java index bb99db7111d..c450b378643 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentServiceMediumTest.java @@ -37,7 +37,6 @@ import org.sonar.server.db.DbClient; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.issue.IssueTesting; import org.sonar.server.issue.index.IssueAuthorizationIndex; -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.IndexDefinition; @@ -99,6 +98,17 @@ public class ComponentServiceMediumTest { } @Test + public void get_by_uuid() throws Exception { + assertThat(service.getByUuid(project.uuid())).isNotNull(); + } + + @Test + public void get_nullable_by_uuid() throws Exception { + assertThat(service.getNullableByUuid(project.uuid())).isNotNull(); + assertThat(service.getNullableByUuid("unknown")).isNull(); + } + + @Test public void update_project_key() throws Exception { ComponentDto file = ComponentTesting.newFileDto(project).setKey("sample:root:src/File.xoo"); tester.get(ComponentDao.class).insert(session, file); @@ -122,15 +132,14 @@ public class ComponentServiceMediumTest { assertThat(service.getNullableByKey("sample2:root:src/File.xoo")).isNotNull(); // Check issue have been updated - assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentKey()).isEqualTo("sample2:root:src/File.xoo"); - assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectKey()).isEqualTo("sample2:root"); +// assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentKey()).isEqualTo("sample2:root:src/File.xoo"); +// assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectKey()).isEqualTo("sample2:root"); // Check that no new issue has been added assertThat(tester.get(SearchClient.class).prepareCount(IndexDefinition.ISSUES.getIndexName()).setTypes(IndexDefinition.ISSUES.getIndexType()).get().getCount()).isEqualTo(1); // Check Issue Authorization index - assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNull(); - assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey("sample2:root")).isNotNull(); + assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.uuid())).isNotNull(); assertThat( tester.get(SearchClient.class).prepareCount(IndexDefinition.ISSUES_AUTHORIZATION.getIndexName()).setTypes(IndexDefinition.ISSUES_AUTHORIZATION.getIndexType()).get() .getCount()).isEqualTo(1); @@ -170,11 +179,11 @@ public class ComponentServiceMediumTest { assertThat(service.getNullableByKey("sample:root2:module:src/File.xoo")).isNotNull(); // Check issue have been updated - assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentKey()).isEqualTo("sample:root2:module:src/File.xoo"); - assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectKey()).isEqualTo(project.key()); +// assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentKey()).isEqualTo("sample:root2:module:src/File.xoo"); +// assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectKey()).isEqualTo(project.key()); // Check Issue Authorization index - assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNotNull(); + assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.uuid())).isNotNull(); // Check dry run cache have been updated -> on a module it's the project cache that is updated assertThat(db.propertiesDao().selectProjectProperties(project.key(), session)).hasSize(1); @@ -283,15 +292,14 @@ public class ComponentServiceMediumTest { assertThat(service.getNullableByKey("sample2:root:module:src/File.xoo")).isNotNull(); // Check issue have been updated - assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentKey()).isEqualTo("sample2:root:module:src/File.xoo"); - assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectKey()).isEqualTo("sample2:root"); +// assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentKey()).isEqualTo("sample2:root:module:src/File.xoo"); +// assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectKey()).isEqualTo("sample2:root"); // Check that no new issue has been added assertThat(tester.get(SearchClient.class).prepareCount(IndexDefinition.ISSUES.getIndexName()).setTypes(IndexDefinition.ISSUES.getIndexType()).get().getCount()).isEqualTo(1); // Check Issue Authorization index - assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNull(); - assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey("sample2:root")).isNotNull(); + assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.uuid())).isNotNull(); assertThat( tester.get(SearchClient.class).prepareCount(IndexDefinition.ISSUES_AUTHORIZATION.getIndexName()).setTypes(IndexDefinition.ISSUES_AUTHORIZATION.getIndexType()).get() .getCount()).isEqualTo(1); diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentTesting.java b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentTesting.java index d729e8329e9..6a9948401b6 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/ComponentTesting.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ComponentTesting.java @@ -24,10 +24,16 @@ import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; import org.sonar.core.component.ComponentDto; +import java.util.UUID; + public class ComponentTesting { public static ComponentDto newFileDto(ComponentDto subProjectOrProject) { return new ComponentDto() + .setUuid(UUID.randomUUID().toString()) + .setProjectUuid(subProjectOrProject.projectUuid()) + .setModuleUuid(!subProjectOrProject.scope().equals(Scopes.PROJECT) ? subProjectOrProject.uuid() : null) + .setModuleUuidPath(subProjectOrProject.moduleUuidPath() == null ? subProjectOrProject.uuid() + "." : subProjectOrProject.moduleUuidPath() + "." + subProjectOrProject.uuid()) .setKey("file") .setName("File") .setLongName("File") @@ -41,6 +47,10 @@ public class ComponentTesting { public static ComponentDto newModuleDto(ComponentDto subProjectOrProject) { return new ComponentDto() + .setUuid(UUID.randomUUID().toString()) + .setProjectUuid(subProjectOrProject.projectUuid()) + .setModuleUuid(!subProjectOrProject.scope().equals(Scopes.PROJECT) ? subProjectOrProject.uuid() : null) + .setModuleUuidPath(subProjectOrProject.moduleUuidPath() == null ? subProjectOrProject.uuid() + "." : subProjectOrProject.moduleUuidPath() + "." + subProjectOrProject.uuid()) .setKey("module") .setName("Module") .setLongName("Module") @@ -53,7 +63,10 @@ public class ComponentTesting { } public static ComponentDto newProjectDto() { + String uuid = UUID.randomUUID().toString(); return new ComponentDto() + .setUuid(uuid) + .setProjectUuid(uuid) .setKey("project") .setName("Project") .setLongName("Project") @@ -64,5 +77,5 @@ public class ComponentTesting { .setLanguage(null) .setEnabled(true); } - + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java index 8860c8c501c..25c6ebdba4b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/DefaultRubyComponentServiceTest.java @@ -65,7 +65,7 @@ public class DefaultRubyComponentServiceTest { } @Test - public void should_find_by_key() { + public void find_by_key() { Component<?> component = mock(Component.class); when(resourceDao.findByKey("struts")).thenReturn(component); @@ -73,6 +73,14 @@ public class DefaultRubyComponentServiceTest { } @Test + public void find_by_uuid() { + ComponentDto component = new ComponentDto(); + when(componentService.getNullableByUuid("ABCD")).thenReturn(component); + + assertThat(service.findByUuid("ABCD")).isEqualTo(component); + } + + @Test public void should_create_component_and_index_it() { String componentKey = "new-project"; String componentName = "New Project"; diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java index b7d7dd30e61..61061de66b9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java @@ -61,6 +61,42 @@ public class ComponentDaoTest extends AbstractDaoTestCase { } @Test + public void get_by_uuid() { + setupData("shared"); + + ComponentDto result = dao.getNullableByUuid(session, "KLMN"); + assertThat(result).isNotNull(); + assertThat(result.uuid()).isEqualTo("KLMN"); + assertThat(result.moduleUuid()).isEqualTo("EFGH"); + assertThat(result.moduleUuidPath()).isEqualTo("ABCD.EFGH."); + assertThat(result.subProjectId()).isEqualTo(2); + assertThat(result.projectUuid()).isEqualTo("ABCD"); + assertThat(result.key()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java"); + assertThat(result.path()).isEqualTo("src/org/struts/RequestContext.java"); + assertThat(result.name()).isEqualTo("RequestContext.java"); + assertThat(result.longName()).isEqualTo("org.struts.RequestContext"); + assertThat(result.qualifier()).isEqualTo("FIL"); + assertThat(result.scope()).isEqualTo("FIL"); + assertThat(result.language()).isEqualTo("java"); + } + + @Test + public void get_by_uuid_on_disabled_component() { + setupData("shared"); + + ComponentDto result = dao.getNullableByUuid(session, "DCBA"); + assertThat(result).isNotNull(); + assertThat(result.isEnabled()).isFalse(); + } + + @Test(expected = NotFoundException.class) + public void fail_to_get_by_uuid_when_component_not_found() { + setupData("shared"); + + dao.getByUuid(session, "unknown"); + } + + @Test public void get_by_key() { setupData("shared"); @@ -74,12 +110,20 @@ public class ComponentDaoTest extends AbstractDaoTestCase { assertThat(result.scope()).isEqualTo("FIL"); assertThat(result.language()).isEqualTo("java"); assertThat(result.subProjectId()).isEqualTo(2); - assertThat(result.projectId()).isEqualTo(1); assertThat(dao.getNullableByKey(session, "unknown")).isNull(); } @Test + public void get_by_key_on_disabled_component() { + setupData("shared"); + + ComponentDto result = dao.getNullableByKey(session, "org.disabled.project"); + assertThat(result).isNotNull(); + assertThat(result.isEnabled()).isFalse(); + } + + @Test public void get_by_key_on_a_root_project() { setupData("shared"); @@ -93,12 +137,11 @@ public class ComponentDaoTest extends AbstractDaoTestCase { assertThat(result.scope()).isEqualTo("PRJ"); assertThat(result.language()).isNull(); assertThat(result.subProjectId()).isNull(); - assertThat(result.projectId()).isEqualTo(1); assertThat(result.getAuthorizationUpdatedAt()).isEqualTo(DateUtils.parseDate("2014-06-18")); } @Test - public void find_by_keys() { + public void get_by_keys() { setupData("shared"); List<ComponentDto> results = dao.getByKeys(session, "org.struts:struts-core:src/org/struts/RequestContext.java"); @@ -120,7 +163,44 @@ public class ComponentDaoTest extends AbstractDaoTestCase { } @Test - public void find_by_ids() { + public void get_by_uuids() { + setupData("shared"); + + List<ComponentDto> results = dao.getByUuids(session, newArrayList("KLMN")); + assertThat(results).hasSize(1); + + ComponentDto result = results.get(0); + assertThat(result).isNotNull(); + assertThat(result.uuid()).isEqualTo("KLMN"); + assertThat(result.moduleUuid()).isEqualTo("EFGH"); + assertThat(result.moduleUuidPath()).isEqualTo("ABCD.EFGH."); + assertThat(result.subProjectId()).isEqualTo(2); + assertThat(result.projectUuid()).isEqualTo("ABCD"); + assertThat(result.key()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java"); + assertThat(result.path()).isEqualTo("src/org/struts/RequestContext.java"); + assertThat(result.name()).isEqualTo("RequestContext.java"); + assertThat(result.longName()).isEqualTo("org.struts.RequestContext"); + assertThat(result.qualifier()).isEqualTo("FIL"); + assertThat(result.scope()).isEqualTo("FIL"); + assertThat(result.language()).isEqualTo("java"); + + assertThat(dao.getByUuids(session, newArrayList("unknown"))).isEmpty(); + } + + @Test + public void get_by_uuids_on_removed_components() { + setupData("shared"); + + List<ComponentDto> results = dao.getByUuids(session, newArrayList("DCBA")); + assertThat(results).hasSize(1); + + ComponentDto result = results.get(0); + assertThat(result).isNotNull(); + assertThat(result.isEnabled()).isFalse(); + } + + @Test + public void get_by_ids() { setupData("shared"); List<ComponentDto> results = dao.getByIds(session, newArrayList(4L)); @@ -149,6 +229,15 @@ public class ComponentDaoTest extends AbstractDaoTestCase { assertThat(dao.getById(4L, session)).isNotNull(); } + @Test + public void get_by_id_on_disabled_component() { + setupData("shared"); + + ComponentDto result = dao.getNullableById(10L, session); + assertThat(result).isNotNull(); + assertThat(result.isEnabled()).isFalse(); + } + @Test(expected = NotFoundException.class) public void fail_to_get_by_id_when_project_not_found() { setupData("shared"); @@ -234,34 +323,34 @@ public class ComponentDaoTest extends AbstractDaoTestCase { setupData("multi-modules"); // Sub project of a file - List<ComponentDto> results = dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts-core:src/org/struts/RequestContext.java")); + List<ComponentDto> results = dao.findSubProjectsByComponentUuids(session, newArrayList("HIJK")); assertThat(results).hasSize(1); assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts-data"); // Sub project of a directory - results = dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts-core:src/org/struts")); + results = dao.findSubProjectsByComponentUuids(session, newArrayList("GHIJ")); assertThat(results).hasSize(1); assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts-data"); // Sub project of a sub module - results = dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts-data")); + results = dao.findSubProjectsByComponentUuids(session, newArrayList("FGHI")); assertThat(results).hasSize(1); assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts"); // Sub project of a module - results = dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts-core")); + results = dao.findSubProjectsByComponentUuids(session, newArrayList("EFGH")); assertThat(results).hasSize(1); assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts"); // Sub project of a project - assertThat(dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts"))).isEmpty(); + assertThat(dao.findSubProjectsByComponentUuids(session, newArrayList("ABCD"))).isEmpty(); // SUb projects of a component and a sub module - assertThat(dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts-core:src/org/struts/RequestContext.java", "org.struts:struts-data"))).hasSize(2); + assertThat(dao.findSubProjectsByComponentUuids(session, newArrayList("HIJK", "FGHI"))).hasSize(2); - assertThat(dao.findSubProjectsByComponentKeys(session, newArrayList("unknown"))).isEmpty(); + assertThat(dao.findSubProjectsByComponentUuids(session, newArrayList("unknown"))).isEmpty(); - assertThat(dao.findSubProjectsByComponentKeys(session, Collections.<String>emptyList())).isEmpty(); + assertThat(dao.findSubProjectsByComponentUuids(session, Collections.<String>emptyList())).isEmpty(); } @Test @@ -346,6 +435,35 @@ public class ComponentDaoTest extends AbstractDaoTestCase { checkTables("insert", "projects"); } + @Test + public void insert_disabled_component() { + when(system2.now()).thenReturn(DateUtils.parseDate("2014-06-18").getTime()); + setupData("empty"); + + ComponentDto componentDto = new ComponentDto() + .setId(1L) + .setUuid("GHIJ") + .setProjectUuid("ABCD") + .setModuleUuid("EFGH") + .setModuleUuidPath("ABCD.EFGH") + .setKey("org.struts:struts-core:src/org/struts/RequestContext.java") + .setName("RequestContext.java") + .setLongName("org.struts.RequestContext") + .setQualifier("FIL") + .setScope("FIL") + .setLanguage("java") + .setPath("src/org/struts/RequestContext.java") + .setSubProjectId(3L) + .setEnabled(false) + .setAuthorizationUpdatedAt(DateUtils.parseDate("2014-06-18")); + + dao.insert(session, componentDto); + session.commit(); + + assertThat(componentDto.getId()).isNotNull(); + checkTables("insert_disabled_component", "projects"); + } + @Test(expected = IllegalStateException.class) public void update() { dao.update(session, new ComponentDto() diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/IndexProjectIssuesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/IndexProjectIssuesStepTest.java index 608f7020e3b..89f66a5a015 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/IndexProjectIssuesStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/IndexProjectIssuesStepTest.java @@ -126,22 +126,6 @@ public class IndexProjectIssuesStepTest { assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey())).isNotNull(); } - private ComponentDto insertPermissionsForProject(String projectKey) { - ComponentDto project = new ComponentDto().setKey(projectKey); - db.componentDao().insert(session, project); - - tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session); - userSession.addProjectPermissions(UserRole.USER, project.key()); - - session.commit(); - - return project; - } - - private void clearIssueIndexToSimulateBatchInsertWithoutIndexing() { - tester.get(BackendCleanup.class).clearIndexType(IndexDefinition.ISSUES); - } - @Test public void index_a_lot_of_issues() throws Exception { ComponentDto project = insertPermissionsForProject(DEFAULT_PROJECT_KEY); @@ -176,4 +160,20 @@ public class IndexProjectIssuesStepTest { Result<Issue> issueIndex = tester.get(IssueIndex.class).search(IssueQuery.builder().build(), new QueryContext()); assertThat(issueIndex.getTotal()).isEqualTo(2001); } + + private ComponentDto insertPermissionsForProject(String projectKey) { + ComponentDto project = ComponentTesting.newProjectDto().setKey(projectKey); + db.componentDao().insert(session, project); + + tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session); + userSession.addProjectPermissions(UserRole.USER, project.key()); + + session.commit(); + + return project; + } + + private void clearIssueIndexToSimulateBatchInsertWithoutIndexing() { + tester.get(BackendCleanup.class).clearIndexType(IndexDefinition.ISSUES); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/SynchronizeProjectPermissionsStepMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/SynchronizeProjectPermissionsStepMediumTest.java index 0a40266086f..99edc5f88f9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/SynchronizeProjectPermissionsStepMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/SynchronizeProjectPermissionsStepMediumTest.java @@ -33,6 +33,7 @@ import org.sonar.core.permission.PermissionFacade; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; import org.sonar.core.user.UserDto; +import org.sonar.server.component.ComponentTesting; import org.sonar.server.db.DbClient; import org.sonar.server.issue.index.IssueAuthorizationDoc; import org.sonar.server.issue.index.IssueAuthorizationIndex; @@ -81,18 +82,6 @@ public class SynchronizeProjectPermissionsStepMediumTest { MyBatis.closeQuietly(session); } - private ComponentDto insertPermissionsForProject(String projectKey) { - ComponentDto project = new ComponentDto().setKey(projectKey); - db.componentDao().insert(session, project); - - tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session); - userSession.addProjectPermissions(UserRole.USER, project.key()); - - session.commit(); - - return project; - } - @Test public void add_project_issue_permission_in_index() throws Exception { ComponentDto project = insertPermissionsForProject(DEFAULT_PROJECT_KEY); @@ -102,7 +91,19 @@ public class SynchronizeProjectPermissionsStepMediumTest { sut.execute(session, reports.get(0)); - IssueAuthorizationDoc issueAuthorizationIndex = tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey()); + IssueAuthorizationDoc issueAuthorizationIndex = tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.uuid()); assertThat(issueAuthorizationIndex).isNotNull(); } + + private ComponentDto insertPermissionsForProject(String projectKey) { + ComponentDto project = ComponentTesting.newProjectDto().setKey(projectKey); + db.componentDao().insert(session, project); + + tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session); + userSession.addProjectPermissions(UserRole.USER, project.key()); + + session.commit(); + + return project; + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ActionServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ActionServiceTest.java index e54d0d75812..b403e5d7f90 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ActionServiceTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ActionServiceTest.java @@ -131,7 +131,7 @@ public class ActionServiceTest { when(userSession.login()).thenReturn("arthur"); when(componentDao.getByKey(session, "struts")).thenReturn(new ComponentDto().setKey("struts")); - when(issueService.getByKeyForUpdate(session, "ABCD")).thenReturn(issue.setRootComponentKey("struts")); + when(issueService.getByKeyForUpdate(session, "ABCD")).thenReturn(issue.setProjectKey("struts")); actions.add("link-to-jira").setConditions(new AlwaysMatch()).setFunctions(function); assertThat(actionService.execute("ABCD", "link-to-jira", userSession)).isNotNull(); 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/InternalRubyIssueServiceTest.java index beb3c74216d..914077f1420 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/InternalRubyIssueServiceTest.java @@ -33,9 +33,7 @@ import org.sonar.api.issue.Issue; import org.sonar.api.issue.action.Action; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.issue.internal.FieldDiffs; -import org.sonar.api.rule.RuleKey; import org.sonar.api.user.User; -import org.sonar.api.utils.DateUtils; import org.sonar.core.issue.DefaultActionPlan; import org.sonar.core.issue.DefaultIssueFilter; import org.sonar.core.resource.ResourceDao; @@ -53,7 +51,6 @@ import java.util.Map; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Maps.newHashMap; -import static java.util.Arrays.asList; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; import static org.mockito.Matchers.any; @@ -68,6 +65,9 @@ public class InternalRubyIssueServiceTest { IssueService issueService; @Mock + IssueQueryService issueQueryService; + + @Mock IssueCommentService commentService; @Mock @@ -94,7 +94,7 @@ public class InternalRubyIssueServiceTest { public void setUp() { ResourceDto project = new ResourceDto().setKey("org.sonar.Sample"); when(resourceDao.getResource(any(ResourceQuery.class))).thenReturn(project); - service = new InternalRubyIssueService(issueService, commentService, changelogService, actionPlanService, resourceDao, actionService, + service = new InternalRubyIssueService(issueService, issueQueryService, commentService, changelogService, actionPlanService, resourceDao, actionService, issueFilterService, issueBulkChangeService); } @@ -574,17 +574,17 @@ public class InternalRubyIssueServiceTest { overrideProps.put("resolved", true); overrideProps.put("pageSize", 20); overrideProps.put("pageIndex", 2); + + when(issueQueryService.createFromMap(overrideProps)).thenReturn(IssueQuery.builder().build()); + service.execute(10L, overrideProps); + ArgumentCaptor<IssueQuery> issueQueryArgumentCaptor = ArgumentCaptor.forClass(IssueQuery.class); ArgumentCaptor<QueryContext> contextArgumentCaptor = ArgumentCaptor.forClass(QueryContext.class); + verify(issueFilterService).execute(issueQueryArgumentCaptor.capture(), contextArgumentCaptor.capture()); verify(issueFilterService).find(eq(10L), any(UserSession.class)); - IssueQuery issueQuery = issueQueryArgumentCaptor.getValue(); - assertThat(issueQuery.componentRoots()).contains("struts"); - assertThat(issueQuery.statuses()).contains("CLOSED"); - assertThat(issueQuery.resolved()).isTrue(); - QueryContext queryContext = contextArgumentCaptor.getValue(); assertThat(queryContext.getLimit()).isEqualTo(20); assertThat(queryContext.getPage()).isEqualTo(2); @@ -679,49 +679,6 @@ public class InternalRubyIssueServiceTest { } @Test - public void create_query_from_parameters() { - Map<String, Object> map = newHashMap(); - map.put("issues", newArrayList("ABCDE1234")); - map.put("severities", newArrayList("MAJOR", "MINOR")); - map.put("statuses", newArrayList("CLOSED")); - map.put("resolutions", newArrayList("FALSE-POSITIVE")); - map.put("resolved", true); - map.put("components", newArrayList("org.apache")); - map.put("componentRoots", newArrayList("org.sonar")); - map.put("reporters", newArrayList("marilyn")); - map.put("assignees", newArrayList("joanna")); - map.put("languages", newArrayList("xoo")); - map.put("assigned", true); - map.put("planned", true); - map.put("hideRules", true); - map.put("createdAfter", "2013-04-16T09:08:24+0200"); - map.put("createdBefore", "2013-04-17T09:08:24+0200"); - map.put("rules", "squid:AvoidCycle,findbugs:NullReference"); - map.put("sort", "CREATION_DATE"); - map.put("asc", true); - - IssueQuery query = InternalRubyIssueService.toQuery(map); - assertThat(query.issueKeys()).containsOnly("ABCDE1234"); - assertThat(query.severities()).containsOnly("MAJOR", "MINOR"); - assertThat(query.statuses()).containsOnly("CLOSED"); - assertThat(query.resolutions()).containsOnly("FALSE-POSITIVE"); - assertThat(query.resolved()).isTrue(); - assertThat(query.components()).containsOnly("org.apache"); - assertThat(query.componentRoots()).containsOnly("org.sonar"); - assertThat(query.reporters()).containsOnly("marilyn"); - assertThat(query.assignees()).containsOnly("joanna"); - assertThat(query.languages()).containsOnly("xoo"); - assertThat(query.assigned()).isTrue(); - assertThat(query.planned()).isTrue(); - assertThat(query.hideRules()).isTrue(); - assertThat(query.rules()).hasSize(2); - assertThat(query.createdAfter()).isEqualTo(DateUtils.parseDateTime("2013-04-16T09:08:24+0200")); - assertThat(query.createdBefore()).isEqualTo(DateUtils.parseDateTime("2013-04-17T09:08:24+0200")); - assertThat(query.sort()).isEqualTo(IssueQuery.SORT_BY_CREATION_DATE); - assertThat(query.asc()).isTrue(); - } - - @Test public void create_context_from_parameters() { Map<String, Object> map = newHashMap(); map.put("pageSize", 10l); @@ -742,15 +699,6 @@ public class InternalRubyIssueServiceTest { assertThat(context.getPage()).isEqualTo(1); } - @Test - public void parse_list_of_rules() { - assertThat(InternalRubyIssueService.toRules(null)).isNull(); - assertThat(InternalRubyIssueService.toRules("")).isEmpty(); - assertThat(InternalRubyIssueService.toRules("squid:AvoidCycle")).containsOnly(RuleKey.of("squid", "AvoidCycle")); - assertThat(InternalRubyIssueService.toRules("squid:AvoidCycle,findbugs:NullRef")).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef")); - assertThat(InternalRubyIssueService.toRules(asList("squid:AvoidCycle", "findbugs:NullRef"))).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef")); - } - private void checkBadRequestException(Exception e, String key, Object... params) { BadRequestException exception = (BadRequestException) e; Message msg = exception.errors().messages().get(0); diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceMediumTest.java index d0186c5b82e..ad789367236 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueBulkChangeServiceMediumTest.java @@ -27,8 +27,6 @@ import org.junit.ClassRule; import org.junit.Test; import org.sonar.api.issue.DefaultTransitions; import org.sonar.api.issue.Issue; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Scopes; import org.sonar.api.security.DefaultGroups; import org.sonar.api.web.UserRole; import org.sonar.core.component.ComponentDto; @@ -37,6 +35,7 @@ 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.ComponentTesting; import org.sonar.server.component.SnapshotTesting; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.component.db.SnapshotDao; @@ -81,18 +80,11 @@ public class IssueBulkChangeServiceMediumTest { rule = RuleTesting.newXooX1(); tester.get(RuleDao.class).insert(session, rule); - project = new ComponentDto() - .setKey("MyProject") - .setLongName("My Project") - .setQualifier(Qualifiers.PROJECT) - .setScope(Scopes.PROJECT); + project = ComponentTesting.newProjectDto().setKey("MyProject"); tester.get(ComponentDao.class).insert(session, project); tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForProject(project)); - file = new ComponentDto() - .setSubProjectId(project.getId()) - .setKey("MyComponent") - .setLongName("My Component"); + file = ComponentTesting.newFileDto(project).setKey("MyComponent"); tester.get(ComponentDao.class).insert(session, file); tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(file, project)); diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java new file mode 100644 index 00000000000..ebb1bd872fe --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueQueryServiceTest.java @@ -0,0 +1,128 @@ +/* + * 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.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.utils.DateUtils; +import org.sonar.core.component.ComponentDto; +import org.sonar.core.persistence.DbSession; +import org.sonar.server.component.db.ComponentDao; +import org.sonar.server.db.DbClient; + +import java.util.Map; + +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Maps.newHashMap; +import static java.util.Arrays.asList; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class IssueQueryServiceTest { + + @Mock + DbClient dbClient; + + @Mock + DbSession session; + + @Mock + ComponentDao componentDao; + + IssueQueryService issueQueryService; + + @Before + public void setUp() throws Exception { + when(dbClient.openSession(false)).thenReturn(session); + when(dbClient.componentDao()).thenReturn(componentDao); + issueQueryService = new IssueQueryService(dbClient); + } + + @Test + public void create_query_from_parameters() { + Map<String, Object> map = newHashMap(); + map.put("issues", newArrayList("ABCDE1234")); + map.put("severities", newArrayList("MAJOR", "MINOR")); + map.put("statuses", newArrayList("CLOSED")); + map.put("resolutions", newArrayList("FALSE-POSITIVE")); + map.put("resolved", true); + map.put("components", newArrayList("org.apache")); + map.put("componentRoots", newArrayList("org.sonar")); + map.put("reporters", newArrayList("marilyn")); + map.put("assignees", newArrayList("joanna")); + map.put("languages", newArrayList("xoo")); + map.put("assigned", true); + map.put("planned", true); + map.put("hideRules", true); + map.put("createdAfter", "2013-04-16T09:08:24+0200"); + map.put("createdBefore", "2013-04-17T09:08:24+0200"); + map.put("rules", "squid:AvoidCycle,findbugs:NullReference"); + map.put("sort", "CREATION_DATE"); + map.put("asc", true); + + when(componentDao.getByKeys(session, newArrayList("org.apache"))).thenReturn(newArrayList(new ComponentDto().setUuid("ABCD"))); + when(componentDao.getByKeys(session, newArrayList("org.sonar"))).thenReturn(newArrayList(new ComponentDto().setUuid("BCDE"))); + + IssueQuery query = issueQueryService.createFromMap(map); + assertThat(query.issueKeys()).containsOnly("ABCDE1234"); + assertThat(query.severities()).containsOnly("MAJOR", "MINOR"); + assertThat(query.statuses()).containsOnly("CLOSED"); + assertThat(query.resolutions()).containsOnly("FALSE-POSITIVE"); + assertThat(query.resolved()).isTrue(); + assertThat(query.components()).containsOnly("ABCD"); + assertThat(query.componentRoots()).containsOnly("BCDE"); + assertThat(query.reporters()).containsOnly("marilyn"); + assertThat(query.assignees()).containsOnly("joanna"); + assertThat(query.languages()).containsOnly("xoo"); + assertThat(query.assigned()).isTrue(); + assertThat(query.planned()).isTrue(); + assertThat(query.hideRules()).isTrue(); + assertThat(query.rules()).hasSize(2); + assertThat(query.createdAfter()).isEqualTo(DateUtils.parseDateTime("2013-04-16T09:08:24+0200")); + assertThat(query.createdBefore()).isEqualTo(DateUtils.parseDateTime("2013-04-17T09:08:24+0200")); + assertThat(query.sort()).isEqualTo(IssueQuery.SORT_BY_CREATION_DATE); + assertThat(query.asc()).isTrue(); + } + + @Test + public void add_unknown_when_no_component_found() { + Map<String, Object> map = newHashMap(); + map.put("components", newArrayList("unknown")); + + IssueQuery query = issueQueryService.createFromMap(map); + assertThat(query.components()).containsOnly("<UNKNOWN>"); + } + + @Test + public void parse_list_of_rules() { + assertThat(IssueQueryService.toRules(null)).isNull(); + assertThat(IssueQueryService.toRules("")).isEmpty(); + assertThat(IssueQueryService.toRules("squid:AvoidCycle")).containsOnly(RuleKey.of("squid", "AvoidCycle")); + assertThat(IssueQueryService.toRules("squid:AvoidCycle,findbugs:NullRef")).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef")); + assertThat(IssueQueryService.toRules(asList("squid:AvoidCycle", "findbugs:NullRef"))).containsOnly(RuleKey.of("squid", "AvoidCycle"), RuleKey.of("findbugs", "NullRef")); + } + +} 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 index 828c1c39bd9..9d4eb444f00 100644 --- 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 @@ -26,12 +26,9 @@ import org.junit.ClassRule; import org.junit.Test; import org.sonar.api.issue.DefaultTransitions; import org.sonar.api.issue.Issue; -import org.sonar.api.resources.Qualifiers; -import org.sonar.api.resources.Scopes; import org.sonar.api.rule.RuleKey; 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; @@ -42,6 +39,7 @@ 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.ComponentTesting; import org.sonar.server.component.SnapshotTesting; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.component.db.SnapshotDao; @@ -49,6 +47,7 @@ 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.IssueDoc; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.rule.RuleTesting; import org.sonar.server.rule.db.RuleDao; @@ -60,7 +59,6 @@ import org.sonar.server.user.MockUserSession; import java.util.Date; import java.util.List; import java.util.Map; -import java.util.UUID; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; @@ -91,18 +89,11 @@ public class IssueServiceMediumTest { rule = RuleTesting.newXooX1(); tester.get(RuleDao.class).insert(session, rule); - project = new ComponentDto() - .setKey("MyProject") - .setLongName("My Project") - .setQualifier(Qualifiers.PROJECT) - .setScope(Scopes.PROJECT); + project = ComponentTesting.newProjectDto(); tester.get(ComponentDao.class).insert(session, project); tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForProject(project)); - file = new ComponentDto() - .setSubProjectId(project.getId()) - .setKey("MyComponent") - .setLongName("My Component"); + file = ComponentTesting.newFileDto(project); tester.get(ComponentDao.class).insert(session, file); tester.get(SnapshotDao.class).insert(session, SnapshotTesting.createForComponent(file, project)); @@ -298,9 +289,9 @@ public class IssueServiceMediumTest { 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()); + IssueDoc manualIssue = (IssueDoc) indexClient.get(IssueIndex.class).getByKey(result.key()); + assertThat(manualIssue.componentUuid()).isEqualTo(file.uuid()); + assertThat(manualIssue.projectUuid()).isEqualTo(project.uuid()); assertThat(manualIssue.ruleKey()).isEqualTo(manualRule.getKey()); assertThat(manualIssue.message()).isEqualTo("Fix it"); assertThat(manualIssue.line()).isEqualTo(10); @@ -420,16 +411,6 @@ public class IssueServiceMediumTest { } 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()); + return IssueTesting.newDto(rule, file, project); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueTesting.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueTesting.java index 0081b1fb7a5..081d65a694c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueTesting.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueTesting.java @@ -47,7 +47,7 @@ public class IssueTesting { .setKee(UUID.randomUUID().toString()) .setRule(rule) .setComponent(file) - .setRootComponent(project) + .setProject(project) .setStatus(Issue.STATUS_OPEN) .setResolution(null) .setSeverity(Severity.MAJOR) @@ -65,7 +65,6 @@ public class IssueTesting { assertThat(issue.assignee()).isEqualTo(dto.getAssignee()); assertThat(issue.authorLogin()).isEqualTo(dto.getAuthorLogin()); assertThat(issue.closeDate()).isEqualTo(dto.getIssueCloseDate()); - assertThat(issue.componentKey()).isEqualTo(dto.getComponentKey()); assertThat(issue.effortToFix()).isEqualTo(dto.getEffortToFix()); assertThat(issue.resolution()).isEqualTo(dto.getResolution()); assertThat(issue.ruleKey()).isEqualTo(RuleKey.of(dto.getRuleRepo(), dto.getRule())); diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ServerIssueStorageTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ServerIssueStorageTest.java index 5372854fd95..044c2d529db 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ServerIssueStorageTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ServerIssueStorageTest.java @@ -73,9 +73,9 @@ public class ServerIssueStorageTest extends AbstractDaoTestCase { setupData("load_component_id_from_db"); session.commit(); - long componentId = storage.componentId(session, new DefaultIssue().setComponentKey("struts:Action.java")); + long componentId = storage.component(session, new DefaultIssue().setComponentKey("struts:Action")).getId(); - assertThat(componentId).isEqualTo(123); + assertThat(componentId).isEqualTo(100); } @Test @@ -83,7 +83,7 @@ public class ServerIssueStorageTest extends AbstractDaoTestCase { setupData("load_project_id_from_db"); session.commit(); - long projectId = storage.projectId(session, new DefaultIssue().setProjectKey("struts")); + long projectId = storage.project(session, new DefaultIssue().setProjectKey("struts")).getId(); assertThat(projectId).isEqualTo(1); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueAuthorizationDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueAuthorizationDaoTest.java index aedf757c64f..d036288669b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueAuthorizationDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/db/IssueAuthorizationDaoTest.java @@ -51,7 +51,7 @@ public class IssueAuthorizationDaoTest extends AbstractDaoTestCase { @Test(expected = IllegalStateException.class) public void get_nullable_by_key_is_not_implemented() { - assertThat(dao.getNullableByKey(session, "sonar")); + assertThat(dao.getNullableByKey(session, "ABCD")); } @Test @@ -69,6 +69,8 @@ public class IssueAuthorizationDaoTest extends AbstractDaoTestCase { public void synchronize_after_since_given_date() { setupData("synchronize_after_since_given_date"); + assertThat(session.getActionCount()).isEqualTo(0); + dao.synchronizeAfter(session, DateUtils.parseDate("2014-09-01")); // SynchronizeAfter adds an implicit action (refresh) after execution of synchronization assertThat(session.getActionCount()).isEqualTo(2); @@ -78,7 +80,9 @@ public class IssueAuthorizationDaoTest extends AbstractDaoTestCase { public void synchronize_after_with_project() { setupData("synchronize_after_with_project"); - dao.synchronizeAfter(session, DateUtils.parseDate("2014-01-01"), ImmutableMap.of(IssueAuthorizationDao.PROJECT_KEY, "org.sonar:sample")); + assertThat(session.getActionCount()).isEqualTo(0); + + dao.synchronizeAfter(session, DateUtils.parseDate("2014-01-01"), ImmutableMap.of(IssueAuthorizationDao.PROJECT_UUID, "ABCD")); // SynchronizeAfter adds an implicit action (refresh) after execution of synchronization assertThat(session.getActionCount()).isEqualTo(2); } 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 e34e044cdab..56b8c1b7fa6 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 @@ -35,8 +35,10 @@ import org.sonar.core.issue.db.IssueDto; import org.sonar.core.permission.PermissionFacade; import org.sonar.core.persistence.DbSession; import org.sonar.core.rule.RuleDto; +import org.sonar.server.component.ComponentTesting; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.db.DbClient; +import org.sonar.server.issue.IssueTesting; import org.sonar.server.issue.index.IssueIndex; import org.sonar.server.platform.Platform; import org.sonar.server.rule.RuleTesting; @@ -45,7 +47,6 @@ import org.sonar.server.search.IndexClient; import org.sonar.server.tester.ServerTester; import java.util.Date; -import java.util.UUID; import static org.fest.assertions.Assertions.assertThat; @@ -78,30 +79,17 @@ public class IssueBackendMediumTest { RuleDto rule = RuleTesting.newXooX1(); tester.get(RuleDao.class).insert(dbSession, rule); - ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("MyProject"); + ComponentDto project = ComponentTesting.newProjectDto(); tester.get(ComponentDao.class).insert(dbSession, project); // project can be seen by anyone tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, dbSession); dbClient.issueAuthorizationDao().synchronizeAfter(dbSession, new Date(0)); - ComponentDto resource = new ComponentDto() - .setKey("MyComponent") - .setId(2L); - tester.get(ComponentDao.class).insert(dbSession, resource); - - IssueDto issue = new IssueDto() - .setIssueCreationDate(new Date()) - .setIssueUpdateDate(new Date()) - .setRule(rule) - .setRootComponent(project) - .setComponent(resource) - .setStatus("OPEN").setResolution("OPEN") - .setKee(UUID.randomUUID().toString()) - .setSeverity("MAJOR") - .setIssueAttributes(KeyValueFormat.format(ImmutableMap.of("key", "value"))); + ComponentDto file = ComponentTesting.newFileDto(project); + tester.get(ComponentDao.class).insert(dbSession, file); + + IssueDto issue = IssueTesting.newDto(rule, file, project).setIssueAttributes(KeyValueFormat.format(ImmutableMap.of("key", "value"))); dbClient.issueDao().insert(dbSession, issue); dbSession.commit(); @@ -117,7 +105,6 @@ public class IssueBackendMediumTest { assertThat(issueDoc.assignee()).isEqualTo(issue.getAssignee()); assertThat(issueDoc.authorLogin()).isEqualTo(issue.getAuthorLogin()); assertThat(issueDoc.closeDate()).isEqualTo(issue.getIssueCloseDate()); - assertThat(issueDoc.componentKey()).isEqualTo(issue.getComponentKey()); assertThat(issueDoc.effortToFix()).isEqualTo(issue.getEffortToFix()); assertThat(issueDoc.resolution()).isEqualTo(issue.getResolution()); assertThat(issueDoc.ruleKey()).isEqualTo(RuleKey.of(issue.getRuleRepo(), issue.getRule())); @@ -130,38 +117,20 @@ public class IssueBackendMediumTest { assertThat(issueDoc.severity()).isEqualTo(issue.getSeverity()); assertThat(issueDoc.attributes()).isEqualTo(KeyValueFormat.parse(issue.getIssueAttributes())); assertThat(issueDoc.attribute("key")).isEqualTo("value"); - - // assertThat(issueDoc.isNew()).isEqualTo(issue.isN()); - // assertThat(issueDoc.comments()).isEqualTo(issue.()); } @Test public void insert_and_find_after_date() throws Exception { - RuleDto rule = RuleTesting.newXooX1(); tester.get(RuleDao.class).insert(dbSession, rule); - ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("MyProject") - .setProjectId_unit_test_only(1L); + ComponentDto project = ComponentTesting.newProjectDto(); tester.get(ComponentDao.class).insert(dbSession, project); - ComponentDto resource = new ComponentDto() - .setId(2L) - .setKey("MyComponent") - .setProjectId_unit_test_only(1L); - tester.get(ComponentDao.class).insert(dbSession, resource); - - IssueDto issue = new IssueDto().setId(1L) - .setRuleId(rule.getId()) - .setRootComponentId(project.getId()) - .setRootComponentKey(project.key()) - .setComponentId(resource.getId()) - .setComponentKey(resource.key()) - .setRule(rule) - .setStatus("OPEN").setResolution("OPEN") - .setKee(UUID.randomUUID().toString()); + ComponentDto file = ComponentTesting.newFileDto(project); + tester.get(ComponentDao.class).insert(dbSession, file); + + IssueDto issue = IssueTesting.newDto(rule, file, project).setId(1L); dbClient.issueDao().insert(dbSession, issue); dbSession.commit(); 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 074fa458a1d..ce9173349e0 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 @@ -65,7 +65,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { assertThat(issue.getKee()).isEqualTo("ABCDE"); assertThat(issue.getId()).isEqualTo(100L); assertThat(issue.getComponentId()).isEqualTo(401); - assertThat(issue.getRootComponentId()).isEqualTo(399); + assertThat(issue.getProjectId()).isEqualTo(399); assertThat(issue.getRuleId()).isEqualTo(500); assertThat(issue.getLanguage()).isEqualTo("java"); assertThat(issue.getSeverity()).isEqualTo("BLOCKER"); @@ -88,7 +88,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { assertThat(issue.getRuleRepo()).isEqualTo("squid"); assertThat(issue.getRule()).isEqualTo("AvoidCycle"); assertThat(issue.getComponentKey()).isEqualTo("Action.java"); - assertThat(issue.getRootComponentKey()).isEqualTo("struts"); + assertThat(issue.getProjectKey()).isEqualTo("struts"); } @Test @@ -102,7 +102,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { assertThat(issue.getKee()).isEqualTo("ABCDE"); assertThat(issue.getId()).isEqualTo(100L); assertThat(issue.getComponentId()).isEqualTo(401); - assertThat(issue.getRootComponentId()).isEqualTo(399); + assertThat(issue.getProjectId()).isEqualTo(399); assertThat(issue.getRuleId()).isEqualTo(500); assertThat(issue.getLanguage()).isEqualTo("java"); assertThat(issue.getSeverity()).isEqualTo("BLOCKER"); @@ -125,7 +125,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { assertThat(issue.getRuleRepo()).isEqualTo("squid"); assertThat(issue.getRule()).isEqualTo("AvoidCycle"); assertThat(issue.getComponentKey()).isEqualTo("Action.java"); - assertThat(issue.getRootComponentKey()).isEqualTo("struts"); + assertThat(issue.getProjectKey()).isEqualTo("struts"); } @Test @@ -139,7 +139,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { assertThat(issue.getKee()).isEqualTo("ABCDE"); assertThat(issue.getActionPlanKey()).isEqualTo("AP-1"); assertThat(issue.getComponentId()).isEqualTo(401); - assertThat(issue.getRootComponentId()).isEqualTo(399); + assertThat(issue.getProjectId()).isEqualTo(399); assertThat(issue.getRuleId()).isEqualTo(500); assertThat(issue.getLanguage()).isEqualTo("java"); assertThat(issue.getSeverity()).isEqualTo("BLOCKER"); @@ -162,7 +162,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { assertThat(issue.getRuleRepo()).isEqualTo("squid"); assertThat(issue.getRule()).isEqualTo("AvoidCycle"); assertThat(issue.getComponentKey()).isEqualTo("Action.java"); - assertThat(issue.getRootComponentKey()).isEqualTo("struts"); + assertThat(issue.getProjectKey()).isEqualTo("struts"); } @Test @@ -189,7 +189,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { IssueDto dto = new IssueDto(); dto.setComponent(new ComponentDto().setKey("struts:Action").setId(123L)); - dto.setRootComponent(new ComponentDto().setKey("struts").setId(100L)); + dto.setProject(new ComponentDto().setKey("struts").setId(100L)); dto.setRule(RuleTesting.newDto(RuleKey.of("squid", "S001")).setId(200)); dto.setKee("ABCDE"); dto.setLine(500); @@ -226,7 +226,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { IssueDto dto = new IssueDto(); dto.setComponent(new ComponentDto().setKey("struts:Action").setId(123L)); - dto.setRootComponent(new ComponentDto().setKey("struts").setId(101L)); + dto.setProject(new ComponentDto().setKey("struts").setId(101L)); dto.setRule(RuleTesting.newDto(RuleKey.of("squid", "S001")).setId(200)); dto.setKee("ABCDE"); dto.setLine(500); 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 ad849b152e8..66a5e701e49 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 @@ -69,6 +69,7 @@ public class IssueAuthorizationIndexMediumTest { public void synchronize_all() throws Exception { project = new ComponentDto() .setKey("Sample") + .setUuid("ABCD") .setAuthorizationUpdatedAt(DateUtils.parseDate("2014-09-11")); db.componentDao().insert(session, project); @@ -87,9 +88,9 @@ public class IssueAuthorizationIndexMediumTest { db.issueAuthorizationDao().synchronizeAfter(session, new Date(0)); session.commit(); - IssueAuthorizationDoc issueAuthorizationDoc = index.getByKey(project.getKey()); + IssueAuthorizationDoc issueAuthorizationDoc = index.getByKey(project.uuid()); assertThat(issueAuthorizationDoc).isNotNull(); - assertThat(issueAuthorizationDoc.project()).isEqualTo("Sample"); + assertThat(issueAuthorizationDoc.project()).isEqualTo("ABCD"); assertThat(issueAuthorizationDoc.permission()).isEqualTo("user"); assertThat(issueAuthorizationDoc.groups()).containsExactly("devs"); assertThat(issueAuthorizationDoc.users()).containsExactly("john"); @@ -97,13 +98,14 @@ public class IssueAuthorizationIndexMediumTest { tester.clearIndexes(); tester.get(Platform.class).executeStartupTasks(); - assertThat(index.getNullableByKey(project.getKey())).isNotNull(); + assertThat(index.getNullableByKey(project.uuid())).isNotNull(); } @Test public void synchronize_all_with_startup_tasks() throws Exception { project = new ComponentDto() .setKey("Sample") + .setUuid("ABCD") .setAuthorizationUpdatedAt(DateUtils.parseDate("2014-09-11")); db.componentDao().insert(session, project); @@ -112,16 +114,17 @@ public class IssueAuthorizationIndexMediumTest { tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), "devs", UserRole.USER, session); session.commit(); - assertThat(index.getNullableByKey(project.getKey())).isNull(); + assertThat(index.getNullableByKey(project.uuid())).isNull(); tester.get(Platform.class).executeStartupTasks(); - assertThat(index.getNullableByKey(project.getKey())).isNotNull(); + assertThat(index.getNullableByKey(project.uuid())).isNotNull(); } @Test public void synchronize_project() throws Exception { project = new ComponentDto() .setKey("Sample") + .setUuid("ABCD") .setAuthorizationUpdatedAt(DateUtils.parseDate("2014-09-11")); db.componentDao().insert(session, project); @@ -136,13 +139,13 @@ public class IssueAuthorizationIndexMediumTest { session.commit(); - assertThat(index.getNullableByKey(project.getKey())).isNull(); - db.issueAuthorizationDao().synchronizeAfter(session, new Date(0), ImmutableMap.of(IssueAuthorizationDao.PROJECT_KEY, project.key())); + assertThat(index.getNullableByKey(project.uuid())).isNull(); + db.issueAuthorizationDao().synchronizeAfter(session, new Date(0), ImmutableMap.of(IssueAuthorizationDao.PROJECT_UUID, project.uuid())); session.commit(); - IssueAuthorizationDoc issueAuthorizationDoc = index.getByKey(project.getKey()); + IssueAuthorizationDoc issueAuthorizationDoc = index.getByKey(project.uuid()); assertThat(issueAuthorizationDoc).isNotNull(); - assertThat(issueAuthorizationDoc.project()).isEqualTo("Sample"); + assertThat(issueAuthorizationDoc.project()).isEqualTo("ABCD"); assertThat(issueAuthorizationDoc.permission()).isEqualTo("user"); assertThat(issueAuthorizationDoc.groups()).containsExactly("devs"); assertThat(issueAuthorizationDoc.users()).containsExactly("john"); @@ -153,6 +156,7 @@ public class IssueAuthorizationIndexMediumTest { public void remove_data_when_synchronizing_project_with_empty_permission() throws Exception { project = new ComponentDto() .setKey("Sample") + .setUuid("ABCD") .setAuthorizationUpdatedAt(DateUtils.parseDate("2014-09-11")); db.componentDao().insert(session, project); @@ -164,21 +168,22 @@ public class IssueAuthorizationIndexMediumTest { // Insert one permission tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), "devs", UserRole.USER, session); - db.issueAuthorizationDao().synchronizeAfter(session, new Date(0), ImmutableMap.of(IssueAuthorizationDao.PROJECT_KEY, project.key())); + db.issueAuthorizationDao().synchronizeAfter(session, new Date(0), ImmutableMap.of(IssueAuthorizationDao.PROJECT_UUID, project.uuid())); session.commit(); - assertThat(index.getByKey(project.getKey())).isNotNull(); + assertThat(index.getByKey(project.uuid())).isNotNull(); // Delete the permission tester.get(PermissionFacade.class).deleteGroupPermission(project.getId(), "devs", UserRole.USER, session); - db.issueAuthorizationDao().synchronizeAfter(session, new Date(0), ImmutableMap.of(IssueAuthorizationDao.PROJECT_KEY, project.key())); + db.issueAuthorizationDao().synchronizeAfter(session, new Date(0), ImmutableMap.of(IssueAuthorizationDao.PROJECT_UUID, project.uuid())); session.commit(); - assertThat(index.getNullableByKey(project.getKey())).isNull(); + assertThat(index.getNullableByKey(project.uuid())).isNull(); } @Test public void delete_index() throws Exception { project = new ComponentDto() .setKey("Sample") + .setUuid("ABCD") .setAuthorizationUpdatedAt(DateUtils.parseDate("2014-09-11")); db.componentDao().insert(session, project); @@ -195,12 +200,12 @@ public class IssueAuthorizationIndexMediumTest { db.issueAuthorizationDao().synchronizeAfter(session, new Date(0)); session.commit(); - assertThat(index.getNullableByKey(project.getKey())).isNotNull(); + assertThat(index.getNullableByKey(project.uuid())).isNotNull(); - db.issueAuthorizationDao().deleteByKey(session, project.key()); + db.issueAuthorizationDao().deleteByKey(session, project.uuid()); session.commit(); - assertThat(index.getNullableByKey(project.getKey())).isNull(); + assertThat(index.getNullableByKey(project.uuid())).isNull(); } } 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 e5f26d0a426..2119cd161e4 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 @@ -40,7 +40,6 @@ import org.sonar.core.rule.RuleDto; import org.sonar.core.user.GroupDto; import org.sonar.core.user.UserDto; import org.sonar.server.component.ComponentTesting; -import org.sonar.server.component.SnapshotTesting; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.db.DbClient; import org.sonar.server.exceptions.NotFoundException; @@ -164,27 +163,38 @@ public class IssueIndexMediumTest { } @Test - public void filter_by_projects() throws Exception { + public void filter_by_component_roots() throws Exception { + ComponentDto module = ComponentTesting.newModuleDto(project); + ComponentDto subModule = ComponentTesting.newModuleDto(module); + ComponentDto file = ComponentTesting.newFileDto(subModule); + tester.get(ComponentDao.class).insert(session, module, subModule, file); + db.issueDao().insert(session, - IssueTesting.newDto(rule, file, project).setRootComponentKey(project.key())); + IssueTesting.newDto(rule, file, project)); session.commit(); - assertThat(index.search(IssueQuery.builder().componentRoots(newArrayList(project.key())).build(), new QueryContext()).getHits()).hasSize(1); - assertThat(index.search(IssueQuery.builder().componentRoots(newArrayList(file.key())).build(), new QueryContext()).getHits()).isEmpty(); + assertThat(index.search(IssueQuery.builder().componentRoots(newArrayList(file.uuid())).build(), new QueryContext()).getHits()).isEmpty(); + assertThat(index.search(IssueQuery.builder().componentRoots(newArrayList(module.uuid())).build(), new QueryContext()).getHits()).hasSize(1); + assertThat(index.search(IssueQuery.builder().componentRoots(newArrayList(subModule.uuid())).build(), new QueryContext()).getHits()).hasSize(1); + assertThat(index.search(IssueQuery.builder().componentRoots(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).hasSize(1); assertThat(index.search(IssueQuery.builder().componentRoots(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty(); } @Test public void filter_by_components() throws Exception { + ComponentDto file1 = ComponentTesting.newFileDto(project); + ComponentDto file2 = ComponentTesting.newFileDto(project); + tester.get(ComponentDao.class).insert(session, file1, file2); + db.issueDao().insert(session, - IssueTesting.newDto(rule, file, project).setComponentKey("file1"), - IssueTesting.newDto(rule, file, project).setComponentKey("file2")); + IssueTesting.newDto(rule, file1, project), + IssueTesting.newDto(rule, file2, project)); session.commit(); - assertThat(index.search(IssueQuery.builder().components(newArrayList("file1", "file2")).build(), new QueryContext()).getHits()).hasSize(2); - assertThat(index.search(IssueQuery.builder().components(newArrayList("file1")).build(), new QueryContext()).getHits()).hasSize(1); + assertThat(index.search(IssueQuery.builder().components(newArrayList(file1.uuid(), file2.uuid())).build(), new QueryContext()).getHits()).hasSize(2); + assertThat(index.search(IssueQuery.builder().components(newArrayList(file1.uuid())).build(), new QueryContext()).getHits()).hasSize(1); assertThat(index.search(IssueQuery.builder().components(newArrayList("unknown")).build(), new QueryContext()).getHits()).isEmpty(); - assertThat(index.search(IssueQuery.builder().components(newArrayList(project.key())).build(), new QueryContext()).getHits()).isEmpty(); + assertThat(index.search(IssueQuery.builder().components(newArrayList(project.uuid())).build(), new QueryContext()).getHits()).isEmpty(); } @Test @@ -671,26 +681,12 @@ public class IssueIndexMediumTest { } @Test - public void synchronize_issues() throws Exception { + public void synchronize_a_lot_of_issues() throws Exception { Integer numberOfIssues = 1000; - ComponentDto project = new ComponentDto() - .setKey("MyProject"); - db.componentDao().insert(session, project); - - // 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)); - - ComponentDto resource = new ComponentDto() - .setSubProjectId(project.getId()) - .setKey("MyComponent"); - db.componentDao().insert(session, resource); - db.snapshotDao().insert(session, SnapshotTesting.createForComponent(resource, project)); - List<String> issueKeys = newArrayList(); for (int i = 0; i < numberOfIssues; i++) { - IssueDto issue = IssueTesting.newDto(rule, resource, project); + IssueDto issue = IssueTesting.newDto(rule, file, project); tester.get(IssueDao.class).insert(session, issue); issueKeys.add(issue.getKey()); } 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 0970c222332..972ec59b217 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 @@ -65,11 +65,13 @@ public class IssueActionsWriterTest { public void write_all_standard_actions() throws Exception { Issue issue = new DefaultIssue() .setKey("ABCD") + .setComponentUuid("BCDE") .setComponentKey("sample:src/main/xoo/sample/Sample.xoo") + .setProjectUuid("ABCD") .setProjectKey("sample") .setRuleKey(RuleKey.of("squid", "AvoidCycle")); - MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.ISSUE_ADMIN, "sample"); + MockUserSession.set().setLogin("john").addProjectUuidPermissions(UserRole.ISSUE_ADMIN, "ABCD"); testActions(issue, "{\"actions\": " + 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 6bd9d45bf77..94cc5f37dbc 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 @@ -44,6 +44,7 @@ import org.sonar.core.issue.db.IssueChangeDao; import org.sonar.core.issue.workflow.Transition; import org.sonar.core.persistence.DbSession; import org.sonar.core.user.DefaultUser; +import org.sonar.server.component.ComponentTesting; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.db.DbClient; import org.sonar.server.debt.DebtModelService; @@ -141,17 +142,37 @@ public class IssueShowActionTest { tester = new WsTester(new IssuesWs( new IssueShowAction(dbClient, issueService, issueChangelogService, commentService, new IssueActionsWriter(issueService, actionService), actionPlanService, userFinder, debtModel, ruleService, i18n, durations), - new SearchAction(mock(DbClient.class), mock(IssueChangeDao.class), mock(IssueService.class), mock(IssueActionsWriter.class), mock(RuleService.class), + new SearchAction(mock(DbClient.class), mock(IssueChangeDao.class), mock(IssueService.class), mock(IssueActionsWriter.class), mock(IssueQueryService.class), + mock(RuleService.class), mock(ActionPlanService.class), mock(UserFinder.class), mock(I18n.class), mock(Durations.class), mock(SourceService.class), mock(ScmWriter.class)))); } @Test public void show_issue() throws Exception { String issueKey = "ABCD"; + + ComponentDto project = ComponentTesting.newProjectDto() + .setId(1L) + .setKey("org.sonar.Sonar") + .setLongName("SonarQube") + .setName("SonarQube"); + when(componentDao.getByUuid(session, project.uuid())).thenReturn(project); + + ComponentDto file = ComponentTesting.newFileDto(project) + .setId(10L) + .setKey("org.sonar.server.issue.IssueClient") + .setLongName("SonarQube :: Issue Client") + .setName("SonarQube :: Issue Client") + .setQualifier("FIL") + .setSubProjectId(1L); + when(componentDao.getByUuid(session, file.uuid())).thenReturn(file); + DefaultIssue issue = new DefaultIssue() .setKey(issueKey) .setComponentKey("org.sonar.server.issue.IssueClient") + .setComponentUuid(file.uuid()) .setProjectKey("org.sonar.Sonar") + .setProjectUuid(project.uuid()) .setRuleKey(RuleKey.of("squid", "AvoidCycle")) .setLine(12) .setMessage("Fix it") @@ -161,24 +182,6 @@ public class IssueShowActionTest { .setCreationDate(issueCreationDate); when(issueService.getByKey(issueKey)).thenReturn(issue); - ComponentDto file = new ComponentDto() - .setId(10L) - .setKey("org.sonar.server.issue.IssueClient") - .setLongName("SonarQube :: Issue Client") - .setName("SonarQube :: Issue Client") - .setQualifier("FIL") - .setSubProjectId(1L) - .setProjectId_unit_test_only(1L); - when(componentDao.getNullableByKey(session, file.key())).thenReturn(file); - - ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("org.sonar.Sonar") - .setLongName("SonarQube") - .setName("SonarQube") - .setProjectId_unit_test_only(1L); - when(componentDao.getNullableById(file.projectId(), session)).thenReturn(project); - MockUserSession.set(); WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey); request.execute().assertJson(getClass(), "show_issue.json"); @@ -187,10 +190,39 @@ public class IssueShowActionTest { @Test public void show_issue_with_sub_project() throws Exception { String issueKey = "ABCD"; + + // Project + ComponentDto project = ComponentTesting.newProjectDto() + .setId(1L) + .setKey("org.sonar.Sonar") + .setLongName("SonarQube"); + when(componentDao.getByUuid(session, project.uuid())).thenReturn(project); + + // Module + ComponentDto module = ComponentTesting.newModuleDto(project) + .setId(2L) + .setKey("org.sonar.server.Server") + .setLongName("SonarQube :: Server") + .setQualifier("BRC") + .setSubProjectId(1L); + when(componentDao.getNullableById(module.getId(), session)).thenReturn(module); + + // File + ComponentDto file = ComponentTesting.newFileDto(module) + .setId(10L) + .setKey("org.sonar.server.issue.IssueClient") + .setLongName("SonarQube :: Issue Client") + .setQualifier("FIL") + .setSubProjectId(2L); + when(componentDao.getByUuid(session, file.uuid())).thenReturn(file); + DefaultIssue issue = new DefaultIssue() .setKey(issueKey) .setComponentKey("org.sonar.server.issue.IssueClient") + .setComponentUuid(file.uuid()) .setProjectKey("org.sonar.Sonar") + .setProjectUuid(project.uuid()) + .setModuleUuid(module.uuid()) .setRuleKey(RuleKey.of("squid", "AvoidCycle")) .setLine(12) .setMessage("Fix it") @@ -200,33 +232,6 @@ public class IssueShowActionTest { .setCreationDate(issueCreationDate); when(issueService.getByKey(issueKey)).thenReturn(issue); - // File - ComponentDto file = new ComponentDto() - .setId(10L) - .setKey("org.sonar.server.issue.IssueClient") - .setLongName("SonarQube :: Issue Client") - .setQualifier("FIL") - .setSubProjectId(2L) - .setProjectId_unit_test_only(1L); - when(componentDao.getNullableByKey(session, file.key())).thenReturn(file); - - // Module - ComponentDto module = new ComponentDto() - .setId(2L) - .setKey("org.sonar.server.Server") - .setLongName("SonarQube :: Server") - .setQualifier("BRC") - .setSubProjectId(1L) - .setProjectId_unit_test_only(1L); - when(componentDao.getNullableById(file.subProjectId(), session)).thenReturn(module); - - // Project - ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("org.sonar.Sonar") - .setLongName("SonarQube"); - when(componentDao.getNullableById(file.projectId(), session)).thenReturn(project); - MockUserSession.set(); WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey); request.execute().assertJson(getClass(), "show_issue_with_sub_project.json"); @@ -235,10 +240,41 @@ public class IssueShowActionTest { @Test public void use_project_and_sub_project_names_if_no_long_name() throws Exception { String issueKey = "ABCD"; + + // Project + ComponentDto project = ComponentTesting.newProjectDto() + .setId(1L) + .setKey("org.sonar.Sonar") + .setName("SonarQube") + .setLongName(null); + when(componentDao.getByUuid(session, project.uuid())).thenReturn(project); + + // Module + ComponentDto module = ComponentTesting.newModuleDto(project) + .setId(2L) + .setKey("org.sonar.server.Server") + .setName("SonarQube :: Server") + .setLongName(null) + .setQualifier("BRC") + .setSubProjectId(1L); + when(componentDao.getNullableById(module.getId(), session)).thenReturn(module); + + // File + ComponentDto file = ComponentTesting.newFileDto(module) + .setId(10L) + .setKey("org.sonar.server.issue.IssueClient") + .setLongName("SonarQube :: Issue Client") + .setQualifier("FIL") + .setSubProjectId(2L); + when(componentDao.getByUuid(session, file.uuid())).thenReturn(file); + DefaultIssue issue = new DefaultIssue() .setKey(issueKey) .setComponentKey("org.sonar.server.issue.IssueClient") + .setComponentUuid(file.uuid()) .setProjectKey("org.sonar.Sonar") + .setProjectUuid(project.uuid()) + .setModuleUuid(module.uuid()) .setRuleKey(RuleKey.of("squid", "AvoidCycle")) .setLine(12) .setEffortToFix(2.0) @@ -249,33 +285,6 @@ public class IssueShowActionTest { .setCreationDate(issueCreationDate); when(issueService.getByKey(issueKey)).thenReturn(issue); - // File - ComponentDto file = new ComponentDto() - .setId(10L) - .setKey("org.sonar.server.issue.IssueClient") - .setLongName("SonarQube :: Issue Client") - .setQualifier("FIL") - .setSubProjectId(2L) - .setProjectId_unit_test_only(1L); - when(componentDao.getNullableByKey(session, file.key())).thenReturn(file); - - // Module - ComponentDto module = new ComponentDto() - .setId(2L) - .setKey("org.sonar.server.Server") - .setName("SonarQube :: Server") - .setQualifier("BRC") - .setSubProjectId(1L) - .setProjectId_unit_test_only(1L); - when(componentDao.getNullableById(file.subProjectId(), session)).thenReturn(module); - - // Project - ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("org.sonar.Sonar") - .setName("SonarQube"); - when(componentDao.getNullableById(file.projectId(), session)).thenReturn(project); - MockUserSession.set(); WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey); request.execute().assertJson(getClass(), "show_issue_with_sub_project.json"); @@ -284,28 +293,32 @@ public class IssueShowActionTest { @Test public void show_issue_on_removed_component() throws Exception { String issueKey = "ABCD"; - DefaultIssue issue = createIssue(); - when(issueService.getByKey(issueKey)).thenReturn(issue); - ComponentDto project = mock(ComponentDto.class); - when(project.key()).thenReturn("org.sonar.Sonar"); - when(project.longName()).thenReturn("SonarQube"); - when(componentDao.getNullableByKey(session, project.key())).thenReturn(project); + ComponentDto project = ComponentTesting.newProjectDto() + .setId(1L) + .setKey("org.sonar.Sonar") + .setLongName("SonarQube") + .setName("SonarQube"); + when(componentDao.getByUuid(session, project.uuid())).thenReturn(project); - MockUserSession.set(); - WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey); - request.execute().assertJson(getClass(), "show_issue_on_removed_component.json"); - } + ComponentDto file = ComponentTesting.newFileDto(project) + .setId(10L) + .setEnabled(false) + .setKey("org.sonar.server.issue.IssueClient") + .setLongName("SonarQube :: Issue Client") + .setName("SonarQube :: Issue Client") + .setQualifier("FIL") + .setSubProjectId(1L); + when(componentDao.getByUuid(session, file.uuid())).thenReturn(file); - @Test - public void show_issue_on_removed_project_and_component() throws Exception { - String issueKey = "ABCD"; - DefaultIssue issue = createIssue(); + DefaultIssue issue = createIssue() + .setComponentUuid(file.uuid()) + .setProjectUuid(project.uuid()); when(issueService.getByKey(issueKey)).thenReturn(issue); MockUserSession.set(); WsTester.TestRequest request = tester.newGetRequest("api/issues", "show").setParam("key", issueKey); - request.execute().assertJson(getClass(), "show_issue_on_removed_project_and_component.json"); + request.execute().assertJson(getClass(), "show_issue_on_removed_component.json"); } @Test @@ -422,7 +435,7 @@ public class IssueShowActionTest { .setMarkdownText("Another comment") .setUserLogin("arthur") .setCreatedAt(date2) - )); + )); when(userFinder.findByLogin("john")).thenReturn(new DefaultUser().setLogin("john").setName("John")); when(userFinder.findByLogin("arthur")).thenReturn(new DefaultUser().setLogin("arthur").setName("Arthur")); @@ -490,9 +503,25 @@ public class IssueShowActionTest { } private DefaultIssue createStandardIssue() { - DefaultIssue issue = createIssue(); - addComponentAndProject(); - return issue; + ComponentDto project = ComponentTesting.newProjectDto() + .setId(1L) + .setKey("org.sonar.Sonar") + .setLongName("SonarQube") + .setName("SonarQube"); + when(componentDao.getByUuid(session, project.uuid())).thenReturn(project); + + ComponentDto file = ComponentTesting.newFileDto(project) + .setId(10L) + .setKey("org.sonar.server.issue.IssueClient") + .setLongName("SonarQube :: Issue Client") + .setName("SonarQube :: Issue Client") + .setQualifier("FIL") + .setSubProjectId(1L); + when(componentDao.getByUuid(session, file.uuid())).thenReturn(file); + + return createIssue() + .setComponentUuid(file.uuid()) + .setProjectUuid(project.uuid()); } private DefaultIssue createIssue() { @@ -504,24 +533,4 @@ public class IssueShowActionTest { .setCreationDate(issueCreationDate); } - private void addComponentAndProject() { - ComponentDto file = new ComponentDto() - .setId(10L) - .setKey("org.sonar.server.issue.IssueClient") - .setLongName("SonarQube :: Issue Client") - .setName("SonarQube :: Issue Client") - .setQualifier("FIL") - .setSubProjectId(1L) - .setProjectId_unit_test_only(1L); - when(componentDao.getNullableByKey(session, file.key())).thenReturn(file); - - ComponentDto project = new ComponentDto() - .setId(1L) - .setKey("org.sonar.Sonar") - .setLongName("SonarQube") - .setName("SonarQube") - .setProjectId_unit_test_only(1L); - when(componentDao.getNullableById(file.projectId(), session)).thenReturn(project); - } - } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java index 4bd49826edd..79ff32334f7 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java @@ -31,6 +31,7 @@ import org.sonar.server.db.DbClient; import org.sonar.server.debt.DebtModelService; import org.sonar.server.issue.IssueChangelogService; import org.sonar.server.issue.IssueCommentService; +import org.sonar.server.issue.IssueQueryService; import org.sonar.server.issue.IssueService; import org.sonar.server.issue.actionplan.ActionPlanService; import org.sonar.server.rule.RuleService; @@ -55,9 +56,11 @@ public class IssuesWsTest { I18n i18n = mock(I18n.class); Durations durations = mock(Durations.class); - showAction = new IssueShowAction(mock(DbClient.class), mock(IssueService.class), issueChangelogService, mock(IssueCommentService.class), actionsWriter, mock(ActionPlanService.class), mock(UserFinder.class), + showAction = new IssueShowAction(mock(DbClient.class), mock(IssueService.class), issueChangelogService, mock(IssueCommentService.class), actionsWriter, + mock(ActionPlanService.class), mock(UserFinder.class), debtModelService, mock(RuleService.class), i18n, durations); - SearchAction searchAction = new SearchAction(mock(DbClient.class), mock(IssueChangeDao.class), mock(IssueService.class), mock(IssueActionsWriter.class), mock(RuleService.class), + SearchAction searchAction = new SearchAction(mock(DbClient.class), mock(IssueChangeDao.class), mock(IssueService.class), mock(IssueActionsWriter.class), + mock(IssueQueryService.class), mock(RuleService.class), mock(ActionPlanService.class), mock(UserFinder.class), mock(I18n.class), mock(Durations.class), mock(SourceService.class), mock(ScmWriter.class)); tester = new WsTester(new IssuesWs(showAction, searchAction)); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java index 38c8c5d8e24..0a3050e7df8 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SearchActionMediumTest.java @@ -40,6 +40,7 @@ import org.sonar.core.rule.RuleDto; import org.sonar.core.source.db.SnapshotSourceDao; import org.sonar.core.source.db.SnapshotSourceDto; import org.sonar.core.user.UserDto; +import org.sonar.server.component.ComponentTesting; import org.sonar.server.component.SnapshotTesting; import org.sonar.server.db.DbClient; import org.sonar.server.issue.IssueTesting; @@ -81,7 +82,7 @@ public class SearchActionMediumTest { .setStatus(RuleStatus.READY); tester.get(RuleDao.class).insert(session, rule); - project = new ComponentDto() + project = ComponentTesting.newProjectDto().setUuid("ABCD").setProjectUuid("ABCD") .setKey("MyProject"); db.componentDao().insert(session, project); db.snapshotDao().insert(session, SnapshotTesting.createForProject(project)); @@ -91,7 +92,7 @@ public class SearchActionMediumTest { tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.CODEVIEWER, session); db.issueAuthorizationDao().synchronizeAfter(session, new Date(0)); - file = new ComponentDto() + file = ComponentTesting.newFileDto(project).setUuid("BCDE") .setKey("MyComponent") .setSubProjectId(project.getId()); db.componentDao().insert(session, file); @@ -147,7 +148,7 @@ public class SearchActionMediumTest { IssueDto issue = IssueTesting.newDto(rule, file, project) .setRule(rule) .setDebt(10L) - .setRootComponent(project) + .setProject(project) .setComponent(file) .setStatus("OPEN").setResolution("OPEN") .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2") @@ -257,19 +258,22 @@ public class SearchActionMediumTest { @Test public void issue_linked_on_removed_file() throws Exception { - IssueDto issue = IssueTesting.newDto(rule, file, project) + ComponentDto removedFile = ComponentTesting.newFileDto(project).setUuid("EDCB") + .setEnabled(false) + .setKey("RemovedComponent") + .setSubProjectId(project.getId()); + db.componentDao().insert(session, removedFile); + + IssueDto issue = IssueTesting.newDto(rule, removedFile, project) .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2") .setRule(rule) - .setRootComponent(project) - .setComponent(file) + .setProject(project) + .setComponent(removedFile) .setStatus("OPEN").setResolution("OPEN") .setSeverity("MAJOR") .setIssueCreationDate(DateUtils.parseDate("2014-09-04")) .setIssueUpdateDate(DateUtils.parseDate("2014-12-04")); db.issueDao().insert(session, issue); - - // Remove the file - db.componentDao().deleteByKey(session, file.key()); session.commit(); WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute(); @@ -300,9 +304,7 @@ public class SearchActionMediumTest { @Test public void components_contains_sub_projects() throws Exception { - ComponentDto project = new ComponentDto() - .setKey("ProjectHavingModule") - .setScope("PRJ"); + ComponentDto project = ComponentTesting.newProjectDto().setKey("ProjectHavingModule"); db.componentDao().insert(session, project); db.snapshotDao().insert(session, SnapshotTesting.createForProject(project)); @@ -310,17 +312,13 @@ public class SearchActionMediumTest { tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session); db.issueAuthorizationDao().synchronizeAfter(session, new Date(0)); - ComponentDto module = new ComponentDto() - .setKey("ModuleHavingFile") + ComponentDto module = ComponentTesting.newFileDto(project).setKey("ModuleHavingFile") .setScope("PRJ") .setSubProjectId(project.getId()); db.componentDao().insert(session, module); db.snapshotDao().insert(session, SnapshotTesting.createForComponent(module, project)); - ComponentDto file = new ComponentDto() - .setKey("FileLinkedToModule") - .setScope("FIL") - .setSubProjectId(module.getId()); + ComponentDto file = ComponentTesting.newFileDto(module).setKey("FileLinkedToModule"); db.componentDao().insert(session, file); db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file, project)); @@ -339,7 +337,7 @@ public class SearchActionMediumTest { .setIssueUpdateDate(DateUtils.parseDate("2014-12-04")) .setRule(rule) .setDebt(10L) - .setRootComponent(project) + .setProject(project) .setComponent(file) .setStatus("OPEN").setResolution("OPEN") .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2") @@ -358,7 +356,7 @@ public class SearchActionMediumTest { .setIssueUpdateDate(DateUtils.parseDate("2014-12-04")) .setRule(rule) .setDebt(10L) - .setRootComponent(project) + .setProject(project) .setComponent(file) .setStatus("OPEN").setResolution("OPEN") .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2") @@ -435,7 +433,7 @@ public class SearchActionMediumTest { .setLine(3) .setRule(rule) .setDebt(10L) - .setRootComponent(project) + .setProject(project) .setComponent(file) .setStatus("OPEN").setResolution("OPEN") .setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2") diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/InternalPermissionServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/InternalPermissionServiceMediumTest.java index 4795da679ed..ed2c9496911 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/InternalPermissionServiceMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/InternalPermissionServiceMediumTest.java @@ -30,6 +30,7 @@ import org.sonar.core.component.ComponentDto; import org.sonar.core.persistence.DbSession; import org.sonar.core.user.RoleDao; import org.sonar.core.user.UserDto; +import org.sonar.server.component.ComponentTesting; import org.sonar.server.db.DbClient; import org.sonar.server.issue.index.IssueAuthorizationDoc; import org.sonar.server.issue.index.IssueAuthorizationIndex; @@ -65,7 +66,7 @@ public class InternalPermissionServiceMediumTest { index = tester.get(IssueAuthorizationIndex.class); service = tester.get(InternalPermissionService.class); - project = new ComponentDto().setKey("Sample").setProjectId_unit_test_only(1L); + project = ComponentTesting.newProjectDto(); db.componentDao().insert(session, project); session.commit(); } @@ -84,7 +85,7 @@ public class InternalPermissionServiceMediumTest { session.commit(); assertThat(tester.get(RoleDao.class).selectUserPermissions(session, user.getLogin(), project.getId())).isEmpty(); - assertThat(index.getNullableByKey(project.getKey())).isNull(); + assertThat(index.getNullableByKey(project.uuid())).isNull(); service.addPermission(params(user.getLogin(), null, project.key(), UserRole.USER)); session.commit(); @@ -93,9 +94,9 @@ public class InternalPermissionServiceMediumTest { assertThat(tester.get(RoleDao.class).selectUserPermissions(session, user.getLogin(), project.getId())).hasSize(1); // Check in index - IssueAuthorizationDoc issueAuthorizationDoc = index.getNullableByKey(project.getKey()); + IssueAuthorizationDoc issueAuthorizationDoc = index.getNullableByKey(project.uuid()); assertThat(issueAuthorizationDoc).isNotNull(); - assertThat(issueAuthorizationDoc.project()).isEqualTo(project.getKey()); + assertThat(issueAuthorizationDoc.project()).isEqualTo(project.uuid()); assertThat(issueAuthorizationDoc.permission()).isEqualTo(UserRole.USER); assertThat(issueAuthorizationDoc.users()).containsExactly(user.getLogin()); assertThat(issueAuthorizationDoc.groups()).isEmpty(); @@ -122,9 +123,9 @@ public class InternalPermissionServiceMediumTest { assertThat(tester.get(RoleDao.class).selectUserPermissions(session, user2.getLogin(), project.getId())).hasSize(1); // Check in index - IssueAuthorizationDoc issueAuthorizationDoc = index.getNullableByKey(project.getKey()); + IssueAuthorizationDoc issueAuthorizationDoc = index.getNullableByKey(project.uuid()); assertThat(issueAuthorizationDoc).isNotNull(); - assertThat(issueAuthorizationDoc.project()).isEqualTo(project.getKey()); + assertThat(issueAuthorizationDoc.project()).isEqualTo(project.uuid()); assertThat(issueAuthorizationDoc.permission()).isEqualTo(UserRole.USER); assertThat(issueAuthorizationDoc.users()).containsExactly(user2.getLogin()); assertThat(issueAuthorizationDoc.groups()).isEmpty(); @@ -146,7 +147,7 @@ public class InternalPermissionServiceMediumTest { assertThat(tester.get(RoleDao.class).selectUserPermissions(session, user.getLogin(), project.getId())).isEmpty(); // Check in index - IssueAuthorizationDoc issueAuthorizationDoc = index.getNullableByKey(project.getKey()); + IssueAuthorizationDoc issueAuthorizationDoc = index.getNullableByKey(project.uuid()); assertThat(issueAuthorizationDoc).isNull(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/InternalPermissionServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/InternalPermissionServiceTest.java index 1f176312171..e9872ad3a1d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/InternalPermissionServiceTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/InternalPermissionServiceTest.java @@ -34,7 +34,6 @@ import org.mockito.runners.MockitoJUnitRunner; import org.sonar.api.resources.Qualifiers; import org.sonar.api.security.DefaultGroups; import org.sonar.api.web.UserRole; -import org.sonar.core.component.AuthorizedComponentDto; import org.sonar.core.component.ComponentDto; import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.permission.PermissionFacade; @@ -45,6 +44,7 @@ import org.sonar.core.resource.ResourceDto; import org.sonar.core.user.GroupDto; import org.sonar.core.user.UserDao; import org.sonar.core.user.UserDto; +import org.sonar.server.component.ComponentTesting; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.db.DbClient; import org.sonar.server.exceptions.BadRequestException; @@ -169,7 +169,8 @@ public class InternalPermissionServiceTest { @Test public void add_component_user_permission() throws Exception { - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(new AuthorizedComponentDto().setId(10L).setKey("org.sample.Sample")); + ComponentDto project = ComponentTesting.newProjectDto().setId(10L).setKey("org.sample.Sample"); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(project); params = buildPermissionChangeParams("user", null, "org.sample.Sample", "user"); setUpComponentUserPermissions("user", 10L, "codeviewer"); @@ -178,7 +179,7 @@ public class InternalPermissionServiceTest { service.addPermission(params); verify(permissionFacade).insertUserPermission(eq(10L), eq(2L), eq("user"), eq(session)); - verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", "org.sample.Sample"))); + verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", project.uuid()))); } @Test @@ -194,7 +195,8 @@ public class InternalPermissionServiceTest { @Test public void remove_component_user_permission() throws Exception { - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(new AuthorizedComponentDto().setId(10L).setKey("org.sample.Sample")); + ComponentDto project = ComponentTesting.newProjectDto().setId(10L).setKey("org.sample.Sample"); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(project); params = buildPermissionChangeParams("user", null, "org.sample.Sample", "codeviewer"); setUpComponentUserPermissions("user", 10L, "codeviewer"); MockUserSession.set().setLogin("admin").addProjectPermissions(UserRole.ADMIN, "org.sample.Sample"); @@ -202,7 +204,7 @@ public class InternalPermissionServiceTest { service.removePermission(params); verify(permissionFacade).deleteUserPermission(eq(10L), eq(2L), eq("codeviewer"), eq(session)); - verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", "org.sample.Sample"))); + verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", project.uuid()))); } @Test @@ -218,7 +220,8 @@ public class InternalPermissionServiceTest { @Test public void add_component_group_permission() throws Exception { - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(new AuthorizedComponentDto().setId(10L).setKey("org.sample.Sample")); + ComponentDto project = ComponentTesting.newProjectDto().setId(10L).setKey("org.sample.Sample"); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(project); params = buildPermissionChangeParams(null, "group", "org.sample.Sample", "user"); setUpGlobalGroupPermissions("group", "codeviewer"); @@ -227,7 +230,7 @@ public class InternalPermissionServiceTest { service.addPermission(params); verify(permissionFacade).insertGroupPermission(eq(10L), eq(2L), eq("user"), eq(session)); - verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", "org.sample.Sample"))); + verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", project.uuid()))); } @Test @@ -242,7 +245,8 @@ public class InternalPermissionServiceTest { @Test public void add_component_permission_to_anyone_group() throws Exception { - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(new AuthorizedComponentDto().setId(10L).setKey("org.sample.Sample")); + ComponentDto project = ComponentTesting.newProjectDto().setId(10L).setKey("org.sample.Sample"); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(project); params = buildPermissionChangeParams(null, DefaultGroups.ANYONE, "org.sample.Sample", "user"); MockUserSession.set().setLogin("admin").addProjectPermissions(UserRole.ADMIN, "org.sample.Sample"); @@ -250,7 +254,7 @@ public class InternalPermissionServiceTest { service.addPermission(params); verify(permissionFacade).insertGroupPermission(eq(10L), eq((Long) null), eq("user"), eq(session)); - verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", "org.sample.Sample"))); + verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", project.uuid()))); } @Test @@ -266,7 +270,8 @@ public class InternalPermissionServiceTest { @Test public void remove_component_group_permission() throws Exception { - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(new AuthorizedComponentDto().setId(10L).setKey("org.sample.Sample")); + ComponentDto project = ComponentTesting.newProjectDto().setId(10L).setKey("org.sample.Sample"); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(project); params = buildPermissionChangeParams(null, "group", "org.sample.Sample", "codeviewer"); setUpComponentGroupPermissions("group", 10L, "codeviewer"); @@ -275,7 +280,7 @@ public class InternalPermissionServiceTest { service.removePermission(params); verify(permissionFacade).deleteGroupPermission(eq(10L), eq(2L), eq("codeviewer"), eq(session)); - verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", "org.sample.Sample"))); + verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", project.uuid()))); } @Test @@ -291,7 +296,8 @@ public class InternalPermissionServiceTest { @Test public void remove_component_permission_from_anyone_group() throws Exception { - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(new AuthorizedComponentDto().setId(10L).setKey("org.sample.Sample")); + ComponentDto project = ComponentTesting.newProjectDto().setId(10L).setKey("org.sample.Sample"); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(project); params = buildPermissionChangeParams(null, DefaultGroups.ANYONE, "org.sample.Sample", "codeviewer"); setUpComponentGroupPermissions(DefaultGroups.ANYONE, 10L, "codeviewer"); @@ -300,7 +306,7 @@ public class InternalPermissionServiceTest { service.removePermission(params); verify(permissionFacade).deleteGroupPermission(eq(10L), eq((Long) null), eq("codeviewer"), eq(session)); - verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", "org.sample.Sample"))); + verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", project.uuid()))); } @Test @@ -316,7 +322,8 @@ public class InternalPermissionServiceTest { @Test public void skip_redundant_add_component_user_permission_change() throws Exception { - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(new AuthorizedComponentDto().setId(10L).setKey("org.sample.Sample")); + ComponentDto project = ComponentTesting.newProjectDto().setId(10L).setKey("org.sample.Sample"); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(project); params = buildPermissionChangeParams("user", null, "org.sample.Sample", "codeviewer"); setUpComponentUserPermissions("user", 10L, "codeviewer"); @@ -341,7 +348,8 @@ public class InternalPermissionServiceTest { @Test public void skip_redundant_add_component_group_permission_change() throws Exception { - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(new AuthorizedComponentDto().setId(10L).setKey("org.sample.Sample")); + ComponentDto project = ComponentTesting.newProjectDto().setId(10L).setKey("org.sample.Sample"); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(project); params = buildPermissionChangeParams(null, "group", "org.sample.Sample", "codeviewer"); setUpComponentGroupPermissions("group", 10L, "codeviewer"); @@ -398,7 +406,8 @@ public class InternalPermissionServiceTest { @Test public void fail_on_insufficient_project_rights() throws Exception { try { - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(new AuthorizedComponentDto().setId(10L).setKey("org.sample.Sample")); + ComponentDto project = ComponentTesting.newProjectDto().setId(10L).setKey("org.sample.Sample"); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(project); params = buildPermissionChangeParams(null, DefaultGroups.ANYONE, "org.sample.Sample", "user"); MockUserSession.set().setLogin("admin").addProjectPermissions(UserRole.ADMIN); @@ -420,15 +429,12 @@ public class InternalPermissionServiceTest { @Test public void apply_permission_template_on_many_projects() throws Exception { - ComponentDto c1 = mock(ComponentDto.class); - when(c1.getId()).thenReturn(1L); - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample1", session)).thenReturn(c1); - ComponentDto c2 = mock(ComponentDto.class); - when(c2.getId()).thenReturn(2L); - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample2", session)).thenReturn(c2); - ComponentDto c3 = mock(ComponentDto.class); - when(c3.getId()).thenReturn(3L); - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample3", session)).thenReturn(c3); + ComponentDto project1 = ComponentTesting.newProjectDto().setId(1L); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample1", session)).thenReturn(project1); + ComponentDto project2 = ComponentTesting.newProjectDto().setId(2L); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample2", session)).thenReturn(project2); + ComponentDto project3 = ComponentTesting.newProjectDto().setId(3L); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample3", session)).thenReturn(project3); params = Maps.newHashMap(); params.put("template_key", "my_template_key"); params.put("components", "org.sample.Sample1,org.sample.Sample2,org.sample.Sample3"); @@ -439,9 +445,9 @@ public class InternalPermissionServiceTest { verify(permissionFacade).applyPermissionTemplate(session, "my_template_key", 2L); verify(permissionFacade).applyPermissionTemplate(session, "my_template_key", 3L); - verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", "org.sample.Sample1"))); - verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", "org.sample.Sample2"))); - verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", "org.sample.Sample3"))); + verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", project1.uuid()))); + verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", project2.uuid()))); + verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", project3.uuid()))); } @Test(expected = ForbiddenException.class) @@ -475,14 +481,13 @@ public class InternalPermissionServiceTest { params.put("template_key", "my_template_key"); params.put("components", "org.sample.Sample"); - ComponentDto c = mock(ComponentDto.class); - when(c.getId()).thenReturn(1L); - when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(c); + ComponentDto project = ComponentTesting.newProjectDto().setId(1L).setKey("org.sample.Sample"); + when(componentDao.getAuthorizedComponentByKey("org.sample.Sample", session)).thenReturn(project); service.applyPermissionTemplate(params); verify(permissionFacade).applyPermissionTemplate(session, "my_template_key", 1L); - verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", "org.sample.Sample"))); + verify(issueAuthorizationDao).synchronizeAfter(eq(session), any(Date.class), eq(ImmutableMap.of("project", project.uuid()))); } @Test(expected = ForbiddenException.class) diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/BackendCleanupMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/BackendCleanupMediumTest.java index 44e9df0edca..54216d5f5c5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/platform/BackendCleanupMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/platform/BackendCleanupMediumTest.java @@ -31,6 +31,7 @@ import org.sonar.core.issue.db.IssueDto; import org.sonar.core.permission.PermissionFacade; import org.sonar.core.persistence.DbSession; import org.sonar.core.rule.RuleDto; +import org.sonar.server.component.ComponentTesting; import org.sonar.server.component.SnapshotTesting; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.db.DbClient; @@ -71,14 +72,11 @@ public class BackendCleanupMediumTest { rule = RuleTesting.newXooX1(); tester.get(RuleDao.class).insert(session, rule); - project = new ComponentDto() - .setKey("MyProject"); + project = ComponentTesting.newProjectDto().setKey("MyProject"); tester.get(ComponentDao.class).insert(session, project); db.snapshotDao().insert(session, SnapshotTesting.createForProject(project)); - file = new ComponentDto() - .setProjectId_unit_test_only(project.getId()) - .setKey("MyComponent"); + file = ComponentTesting.newFileDto(project).setKey("MyComponent"); tester.get(ComponentDao.class).insert(session, file); db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file, project)); @@ -110,7 +108,7 @@ public class BackendCleanupMediumTest { // Nothing should be removed from indexes assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey())).isNotNull(); - assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNotNull(); + assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.uuid())).isNotNull(); assertThat(tester.get(RuleIndex.class).getNullableByKey(rule.getKey())).isNotNull(); } @@ -127,7 +125,7 @@ public class BackendCleanupMediumTest { // Everything should be removed from indexes assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey())).isNull(); - assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNull(); + assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.uuid())).isNull(); assertThat(tester.get(RuleIndex.class).getNullableByKey(rule.getKey())).isNull(); } @@ -144,7 +142,7 @@ public class BackendCleanupMediumTest { // Everything should be removed from indexes assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey())).isNull(); - assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNull(); + assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.uuid())).isNull(); assertThat(tester.get(RuleIndex.class).getNullableByKey(rule.getKey())).isNull(); } @@ -158,7 +156,7 @@ public class BackendCleanupMediumTest { assertThat(tester.get(ComponentDao.class).getNullableByKey(session, file.key())).isNull(); assertThat(tester.get(IssueDao.class).getNullableByKey(session, issue.getKey())).isNull(); assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey())).isNull(); - assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.getKey())).isNull(); + assertThat(tester.get(IssueAuthorizationIndex.class).getNullableByKey(project.uuid())).isNull(); // Every rules should not be removed (from db and indexes) assertThat(tester.get(RuleDao.class).getNullableByKey(session, rule.getKey())).isNotNull(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/MockUserSession.java b/server/sonar-server/src/test/java/org/sonar/server/user/MockUserSession.java index 834611d6c93..9af4123fef0 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/MockUserSession.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/MockUserSession.java @@ -41,6 +41,7 @@ public class MockUserSession extends UserSession { private MockUserSession() { globalPermissions = Collections.emptyList(); projectKeyByPermission = HashMultimap.create(); + projectUuidByPermission = HashMultimap.create(); authorizationDao = mock(AuthorizationDao.class); resourceDao = mock(ResourceDao.class); } @@ -91,6 +92,12 @@ public class MockUserSession extends UserSession { return this; } + public MockUserSession addProjectUuidPermissions(String projectPermission, String... projectUuids) { + this.projectPermissions.add(projectPermission); + this.projectUuidByPermission.putAll(projectPermission, newArrayList(projectUuids)); + return this; + } + public MockUserSession addComponentPermission(String projectPermission, String projectKey, String componentKey) { this.projectKeyByComponentKey.put(componentKey, projectKey); addProjectPermissions(projectPermission, projectKey); diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/UserSessionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/UserSessionTest.java index ae33bb0998d..59a76d1fe9c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/UserSessionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/UserSessionTest.java @@ -120,6 +120,17 @@ public class UserSessionTest { } @Test + public void has_project_permission_by_uuid() throws Exception { + AuthorizationDao authorizationDao = mock(AuthorizationDao.class); + UserSession session = new SpyUserSession("marius", authorizationDao).setUserId(1); + when(authorizationDao.selectAuthorizedRootProjectsUuids(1, UserRole.USER)).thenReturn(newArrayList("ABCD")); + + assertThat(session.hasProjectPermissionByUuid(UserRole.USER, "ABCD")).isTrue(); + assertThat(session.hasProjectPermissionByUuid(UserRole.CODEVIEWER, "ABCD")).isFalse(); + assertThat(session.hasProjectPermissionByUuid(UserRole.ADMIN, "ABCD")).isFalse(); + } + + @Test public void check_project_permission_ok() throws Exception { AuthorizationDao authorizationDao = mock(AuthorizationDao.class); UserSession session = new SpyUserSession("marius", authorizationDao).setUserId(1); diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/delete-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/delete-result.xml index 928b1f46470..35528074855 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/delete-result.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/delete-result.xml @@ -30,7 +30,7 @@ <!-- module --> <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" deprecated_kee="[null]" - uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="ABCD" + uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="ABCD." scope="PRJ" qualifier="BRC" long_name="Struts Core" description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" created_at="[null]" authorization_updated_at="[null]" /> <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" @@ -45,7 +45,7 @@ <!-- directory --> <projects long_name="org.struts" id="3" scope="DIR" qualifier="DIR" kee="org.struts:struts-core:src/org/struts" deprecated_kee="[null]" - uuid="GHIJ" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path="ABCD.EFGH" + uuid="GHIJ" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path="ABCD.EFGH." name="src/org/struts" root_id="2" description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="src/org/struts" created_at="[null]" authorization_updated_at="[null]" /> @@ -76,4 +76,9 @@ depth="[null]" scope="FIL" qualifier="CLA" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="1.2.3."/> + <projects id="10" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.disabled.project" name="Disabled Project" + uuid="DCBA" project_uuid="DCBA" module_uuid="[null]" module_uuid_path="[null]" + description="the description" long_name="Disabled project" + enabled="[false]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="2014-06-18" /> + </dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/insert_disabled_component-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/insert_disabled_component-result.xml new file mode 100644 index 00000000000..477c9bdd09a --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/insert_disabled_component-result.xml @@ -0,0 +1,10 @@ +<dataset> + + <projects id="1" kee="org.struts:struts-core:src/org/struts/RequestContext.java" name="RequestContext.java" long_name="org.struts.RequestContext" + uuid="GHIJ" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path="ABCD.EFGH" + qualifier="FIL" scope="FIL" language="java" path="src/org/struts/RequestContext.java" root_id="3" + description="[null]" enabled="[false]" copy_resource_id="[null]" person_id="[null]" deprecated_kee="[null]" + authorization_updated_at="2014-06-18" created_at="2014-06-18" + /> + +</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/multi-modules.xml b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/multi-modules.xml index 771faf6ec97..49ff0123e76 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/multi-modules.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/multi-modules.xml @@ -6,6 +6,7 @@ <!-- root project --> <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="[null]" description="the description" long_name="Apache Struts" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="[null]" /> <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" @@ -29,6 +30,7 @@ <!-- module --> <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" + uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="ABCD." scope="PRJ" qualifier="BRC" long_name="Struts Core" description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" /> <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" @@ -43,6 +45,7 @@ <!-- sub module --> <projects id="3" root_id="1" kee="org.struts:struts-data" name="Struts Data" + uuid="FGHI" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path="ABCD.EFGH." scope="PRJ" qualifier="BRC" long_name="Struts Data" description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" /> <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" @@ -57,6 +60,7 @@ <!-- directory --> <projects long_name="org.struts" id="4" scope="DIR" qualifier="DIR" kee="org.struts:struts-core:src/org/struts" + uuid="GHIJ" project_uuid="ABCD" module_uuid="FGHI" module_uuid_path="ABCD.EFGH.FGHI." name="src/org/struts" root_id="3" description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="src/org/struts" authorization_updated_at="[null]" /> @@ -72,6 +76,7 @@ <!-- file --> <projects long_name="org.struts.RequestContext" id="5" scope="FIL" qualifier="FIL" kee="org.struts:struts-core:src/org/struts/RequestContext.java" + uuid="HIJK" project_uuid="ABCD" module_uuid="GHIJ" module_uuid_path="ABCD.EFGH.FGHI.GHIJ." name="RequestContext.java" root_id="3" description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="src/org/struts/RequestContext.java" authorization_updated_at="[null]" /> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/shared.xml index 97b8358cd4a..a8937014b19 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/shared.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/shared.xml @@ -30,7 +30,7 @@ <!-- module --> <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" - uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="ABCD" + uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="ABCD." scope="PRJ" qualifier="BRC" long_name="Struts Core" description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" /> <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1" @@ -45,7 +45,7 @@ <!-- directory --> <projects long_name="org.struts" id="3" scope="DIR" qualifier="DIR" kee="org.struts:struts-core:src/org/struts" - uuid="GHIJ" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path="ABCD.EFGH" + uuid="GHIJ" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path="ABCD.EFGH." name="src/org/struts" root_id="2" description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="src/org/struts" authorization_updated_at="[null]" /> @@ -61,7 +61,7 @@ <!-- file --> <projects long_name="org.struts.RequestContext" id="4" scope="FIL" qualifier="FIL" kee="org.struts:struts-core:src/org/struts/RequestContext.java" - uuid="KLMN" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path="ABCD.EFGH" + uuid="KLMN" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path="ABCD.EFGH." name="RequestContext.java" root_id="2" description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="src/org/struts/RequestContext.java" authorization_updated_at="[null]" /> @@ -76,4 +76,10 @@ depth="[null]" scope="FIL" qualifier="CLA" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="1.2.3."/> + <!-- Disabled projects --> + <projects id="10" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.disabled.project" name="Disabled Project" + uuid="DCBA" project_uuid="DCBA" module_uuid="[null]" module_uuid_path="[null]" + description="the description" long_name="Disabled project" + enabled="[false]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="2014-06-18" /> + </dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/load_component_id_from_db.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/load_component_id_from_db.xml index cf7e75fd7f7..157531639cc 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/load_component_id_from_db.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/load_component_id_from_db.xml @@ -1,3 +1,7 @@ <dataset> - <projects id="123" kee="struts:Action.java" /> -</dataset>
\ No newline at end of file + <projects id="10" scope="PRJ" qualifier="TRK" kee="struts" name="Struts"/> + <snapshots id="10" project_id="10" root_project_id="[null]" islast="[true]"/> + + <projects id="100" scope="FIL" qualifier="CLA" kee="struts:Action" name="Action"/> + <snapshots id="100" project_id="100" root_project_id="10" islast="[true]"/> +</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/should_insert_new_issues.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/should_insert_new_issues.xml index 683ead42b1f..157531639cc 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/should_insert_new_issues.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/should_insert_new_issues.xml @@ -1,4 +1,7 @@ <dataset> <projects id="10" scope="PRJ" qualifier="TRK" kee="struts" name="Struts"/> + <snapshots id="10" project_id="10" root_project_id="[null]" islast="[true]"/> + <projects id="100" scope="FIL" qualifier="CLA" kee="struts:Action" name="Action"/> + <snapshots id="100" project_id="100" root_project_id="10" islast="[true]"/> </dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/should_update_issues.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/should_update_issues.xml index 8b552f4bd7f..4a49fca856a 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/should_update_issues.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ServerIssueStorageTest/should_update_issues.xml @@ -1,7 +1,10 @@ <dataset> <projects id="10" scope="PRJ" qualifier="TRK" kee="struts" name="Struts"/> + <snapshots id="10" project_id="10" root_project_id="[null]" islast="[true]"/> + <projects id="100" scope="FIL" qualifier="CLA" kee="struts:Action" name="Action"/> + <snapshots id="100" project_id="100" root_project_id="10" islast="[true]"/> <issues id="1" kee="ABCDE" diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_since_beginning.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_since_beginning.xml index 9236b6d6391..aed962754dc 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_since_beginning.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_since_beginning.xml @@ -1,6 +1,7 @@ <dataset> - <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + <projects id="1" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="[null]" + root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" description="the description" long_name="Apache Struts" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="2014-01-01"/> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_since_given_date.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_since_given_date.xml index eff050279eb..dd4dc6a1405 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_since_given_date.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_since_given_date.xml @@ -1,11 +1,13 @@ <dataset> - <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + <projects id="1" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="[null]" + root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" description="the description" long_name="Apache Struts" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="2014-01-01"/> - <projects id="2" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.sonar.sample" name="Sample" + <projects id="2" uuid="BCDE" project_uuid="BCDE" module_uuid="[null]" module_uuid_path="[null]" + root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.sonar.sample" name="Sample" description="the description" long_name="Sample" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="2014-09-05"/> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_with_project.xml b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_with_project.xml index c28f48753c7..f1d96456a66 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_with_project.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/db/IssueAuthorizationDaoTest/synchronize_after_with_project.xml @@ -8,7 +8,8 @@ <!-- Project 1 --> - <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + <projects id="1" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="[null]" + root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" description="the description" long_name="Apache Struts" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="2014-01-01"/> @@ -20,7 +21,8 @@ <!-- Project 2 --> - <projects id="2" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.sonar:sample" name="Struts" + <projects id="2" uuid="BCDE" project_uuid="BCDE" module_uuid="[null]" module_uuid_path="[null]" + root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.sonar:sample" name="Struts" description="the description" long_name="SonarQube Sample" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="2014-01-02"/> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue.json index 6a0eb80bcff..e53e2b29fe6 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue.json @@ -4,6 +4,7 @@ "component": "org.sonar.server.issue.IssueClient", "componentLongName": "SonarQube :: Issue Client", "componentQualifier": "FIL", + "componentEnabled": true, "project": "org.sonar.Sonar", "projectName": "SonarQube", "rule": "squid:AvoidCycle", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_on_removed_component.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_on_removed_component.json index 74542d5ed0e..33d376a5cc1 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_on_removed_component.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_on_removed_component.json @@ -2,7 +2,11 @@ "issue": { "key": "ABCD", "component": "org.sonar.server.issue.IssueClient", + "componentLongName": "SonarQube :: Issue Client", + "componentQualifier": "FIL", + "componentEnabled": false, "project": "org.sonar.Sonar", + "projectName": "SonarQube", "rule": "squid:AvoidCycle", "ruleName": "Avoid cycle", "creationDate": "2014-01-22T19:10:03+0100", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_on_removed_project_and_component.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_on_removed_project_and_component.json deleted file mode 100644 index 74542d5ed0e..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_on_removed_project_and_component.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "issue": { - "key": "ABCD", - "component": "org.sonar.server.issue.IssueClient", - "project": "org.sonar.Sonar", - "rule": "squid:AvoidCycle", - "ruleName": "Avoid cycle", - "creationDate": "2014-01-22T19:10:03+0100", - "fCreationDate": "Jan 22, 2014 10:03 AM", - "transitions": [], - "actions": [], - "comments": [], - "changelog": [ - { - "creationDate": "2014-01-22T19:10:03+0100", - "fCreationDate": "Jan 22, 2014 10:03 AM", - "diffs": ["Created"] - } - ] - } -} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_action_plan.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_action_plan.json index 71dff779e78..c03d5c8a8fa 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_action_plan.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_action_plan.json @@ -4,6 +4,7 @@ "component": "org.sonar.server.issue.IssueClient", "componentLongName": "SonarQube :: Issue Client", "componentQualifier": "FIL", + "componentEnabled": true, "project": "org.sonar.Sonar", "projectName": "SonarQube", "rule": "squid:AvoidCycle", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_actions.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_actions.json index eb7f97febca..ea0653f371b 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_actions.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_actions.json @@ -4,6 +4,7 @@ "component": "org.sonar.server.issue.IssueClient", "componentLongName": "SonarQube :: Issue Client", "componentQualifier": "FIL", + "componentEnabled": true, "project": "org.sonar.Sonar", "projectName": "SonarQube", "rule": "squid:AvoidCycle", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_changelog.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_changelog.json index ceef684036d..4a1889d57ab 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_changelog.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_changelog.json @@ -4,6 +4,7 @@ "component": "org.sonar.server.issue.IssueClient", "componentLongName": "SonarQube :: Issue Client", "componentQualifier": "FIL", + "componentEnabled": true, "project": "org.sonar.Sonar", "projectName": "SonarQube", "rule": "squid:AvoidCycle", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_characteristics.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_characteristics.json index 833d8006244..b227aba9c71 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_characteristics.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_characteristics.json @@ -4,6 +4,7 @@ "component": "org.sonar.server.issue.IssueClient", "componentLongName": "SonarQube :: Issue Client", "componentQualifier": "FIL", + "componentEnabled": true, "project": "org.sonar.Sonar", "projectName": "SonarQube", "rule": "squid:AvoidCycle", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_comments.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_comments.json index 8eba44a1006..6072b30aefa 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_comments.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_comments.json @@ -4,6 +4,7 @@ "component": "org.sonar.server.issue.IssueClient", "componentLongName": "SonarQube :: Issue Client", "componentQualifier": "FIL", + "componentEnabled": true, "project": "org.sonar.Sonar", "projectName": "SonarQube", "rule": "squid:AvoidCycle", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_dates.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_dates.json index de7b32bec99..5a7b591e687 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_dates.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_dates.json @@ -4,6 +4,7 @@ "component": "org.sonar.server.issue.IssueClient", "componentLongName": "SonarQube :: Issue Client", "componentQualifier": "FIL", + "componentEnabled": true, "project": "org.sonar.Sonar", "projectName": "SonarQube", "rule": "squid:AvoidCycle", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_sub_project.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_sub_project.json index aa7b9e3860d..a4546b2ee56 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_sub_project.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_sub_project.json @@ -4,6 +4,7 @@ "component": "org.sonar.server.issue.IssueClient", "componentLongName": "SonarQube :: Issue Client", "componentQualifier": "FIL", + "componentEnabled": true, "project": "org.sonar.Sonar", "projectName": "SonarQube", "subProjectName": "SonarQube :: Server", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_technical_debt.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_technical_debt.json index 4a42e205d75..ff29d2d2b49 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_technical_debt.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_technical_debt.json @@ -4,6 +4,7 @@ "component": "org.sonar.server.issue.IssueClient", "componentLongName": "SonarQube :: Issue Client", "componentQualifier": "FIL", + "componentEnabled": true, "project": "org.sonar.Sonar", "projectName": "SonarQube", "rule": "squid:AvoidCycle", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_transitions.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_transitions.json index ed14d165979..9d06cd9d942 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_transitions.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_transitions.json @@ -4,6 +4,7 @@ "component": "org.sonar.server.issue.IssueClient", "componentLongName": "SonarQube :: Issue Client", "componentQualifier": "FIL", + "componentEnabled": true, "project": "org.sonar.Sonar", "projectName": "SonarQube", "rule": "squid:AvoidCycle", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_users.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_users.json index 5f69ff25f67..eb96ea579a5 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_users.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/IssueShowActionTest/show_issue_with_users.json @@ -4,6 +4,7 @@ "component": "org.sonar.server.issue.IssueClient", "componentLongName": "SonarQube :: Issue Client", "componentQualifier": "FIL", + "componentEnabled": true, "project": "org.sonar.Sonar", "projectName": "SonarQube", "rule": "squid:AvoidCycle", diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json index 8ca688f5c42..acfba96d5e7 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/display_facets.json @@ -44,7 +44,7 @@ "property": "componentRoots", "values": [ { - "val": "MyProject", + "val": "ABCD", "count": 1 } ] diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue.json index 4700d9a1bef..f2bf146d712 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue.json @@ -31,14 +31,19 @@ ], "components": [ { - "key": "MyComponent" + "uuid": "BCDE", + "key": "MyComponent", + "enabled" : true }, { - "key": "MyProject" + "uuid": "ABCD", + "key": "MyProject", + "enabled" : true } ], "projects": [ { + "uuid": "ABCD", "key": "MyProject" } ], diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_linked_on_removed_file.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_linked_on_removed_file.json index e6eba81ea5f..78eb3deaf01 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_linked_on_removed_file.json +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/SearchActionMediumTest/issue_linked_on_removed_file.json @@ -2,7 +2,7 @@ "issues": [ { "key": "82fd47d4-b650-4037-80bc-7b112bd4eac2", - "component": "MyComponent", + "component": "RemovedComponent", "project": "MyProject", "rule": "xoo:x1", "status": "OPEN", @@ -11,5 +11,17 @@ "updateDate": "2014-12-04T00:00:00+0100", "fUpdateAge": "less than a minute" } + ], + "components": [ + { + "uuid": "EDCB", + "key": "RemovedComponent", + "enabled" : false + }, + { + "uuid": "ABCD", + "key": "MyProject", + "enabled" : true + } ] } diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/issue_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/issue_controller.rb index 66407eb2395..993dcc86d63 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/issue_controller.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/issue_controller.rb @@ -206,8 +206,8 @@ class IssueController < ApplicationController def init_issue(issue_key) @issue = Internal.issues.getIssueByKey(issue_key) - @project = Internal.component_api.findByKey(@issue.projectKey()) - @component = Internal.component_api.findByKey(@issue.componentKey()) + @project = Internal.component_api.findByUuid(@issue.projectUuid()) + @component = Internal.component_api.findByUuid(@issue.componentUuid()) @rule = Internal.rules.findByKey(@issue.ruleKey().to_s) @action_plan = Internal.issues.findActionPlan(@issue.actionPlanKey()) if @issue.actionPlanKey() @comments = Internal.issues.findComments(issue_key) @@ -224,7 +224,7 @@ class IssueController < ApplicationController @users[u.login()] = u end - resource = Project.by_key(@issue.componentKey()) + resource = Project.by_key(@component.key()) @snapshot = resource.last_snapshot if resource.last_snapshot end diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb index 887e8e63797..7d0474c8e00 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/controllers/issues_controller.rb @@ -138,7 +138,8 @@ class IssuesController < ApplicationController else @issues = Internal.issues.execute(issues_query_params).issues() end - @projects = Set.new(@issues.map {|issue| issue.projectKey()}) + + @projectUuids = Set.new(@issues.map {|issue| issue.projectUuid()}) render :partial => 'issues/bulk_change_form' end diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb index 6e6e6dc93cd..01395bc3cd9 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_issue.html.erb @@ -1,4 +1,5 @@ -<div id="issue-<%= u issue.key -%>" class="code-issue code-issue-collapsed" data-issue-key="<%= issue.key -%>" data-issue-component="<%= issue.componentKey() -%>" data-issue-rule="<%= u issue.ruleKey().toString() -%>"> +<!-- TODO @component.key() should be replaced by issue.componentUuid --> +<div id="issue-<%= u issue.key -%>" class="code-issue code-issue-collapsed" data-issue-key="<%= issue.key -%>" data-issue-component="<%= @component.key() -%>" data-issue-rule="<%= u issue.ruleKey().toString() -%>"> <div class="code-issue-name code-issue-toggle"> <div class="code-issue-name-rule"> <i class="icon-severity-<%= issue.severity.downcase -%>"></i> @@ -76,7 +77,7 @@ <div class="dropdown"> <a href="#" class="link-action link-more" onclick="showDropdownMenuOnElement($j(this).next('.dropdown-menu')); return false;"><%= message('more_actions') -%></a> <ul style="display: none" class="dropdown-menu"> - <% if Java::OrgSonarServerUser::UserSession.get().hasProjectPermission('issueadmin', issue.projectKey) %> + <% if Java::OrgSonarServerUser::UserSession.get().hasProjectPermissionByUuid('issueadmin', issue.projectUuid()) %> <% unless issue.resolution %> <li> <a href="#" onclick="return issueForm('severity', this)" class="link-action spacer-right"><%= message("issue.set_severity") -%></a> diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show.html.erb index d6e5b8f3923..5b5c3b43895 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show.html.erb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issue/_show.html.erb @@ -5,18 +5,18 @@ component = @component %> - <% if project && @issue.componentKey() != project.key() %> + <% if @issue.componentUuid() != project.uuid() %> <div class="subtitle"> <%= h project.longName() -%> </div> <% end %> <span class="h1"> - <% if component %> + <% if component.isEnabled() %> <%= qualifier_icon(component) %> <a href="<%= ApplicationController.root_context -%>/component/index#component=<%= component.key() -%>&tab=issues" class="issue-component-link" onclick="window.open(this.href,'resource-<%= component.key().parameterize -%>','height=800,width=900,scrollbars=1,resizable=1');return false;"><%= h component.longName() -%></a> <% else %> - <%= h @issue.componentKey() %> [<del><%= message('issue.component_deleted') %></del>] + <%= h component.key() %> [<del><%= message('issue.component_deleted') %></del>] <% end %> </span> </div> diff --git a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issues/_bulk_change_form.html.erb b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issues/_bulk_change_form.html.erb index 729cd13e2cf..3802a05e99d 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/app/views/issues/_bulk_change_form.html.erb +++ b/server/sonar-web/src/main/webapp/WEB-INF/app/views/issues/_bulk_change_form.html.erb @@ -1,5 +1,6 @@ <% - project_key = @projects.to_a.first if !@projects.empty? && @projects.to_a.size == 1 + project_uuid = @projectUuids.to_a.first if !@projectUuids.empty? && @projectUuids.to_a.size == 1 + project_key = Internal.component_api.findByUuid(project_uuid).key() if project_uuid max_page_size_reached = @issues.size >= Internal.issues.maxPageSize() transitions_by_issues = {} @@ -16,7 +17,7 @@ transitions_by_issues[transition.key] = issues_for_transition end unresolved_issues += 1 unless issue.resolution() - if Java::OrgSonarServerUser::UserSession.get().hasProjectPermission('issueadmin', issue.projectKey) + if Java::OrgSonarServerUser::UserSession.get().hasProjectPermissionByUuid('issueadmin', issue.projectUuid) unresolved_issues_user_can_admin += 1 unless issue.resolution() end at_least_one_issue_is_planned ||= issue.actionPlanKey() diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ScanIssueStorage.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ScanIssueStorage.java index 4ca89943fc1..1247db7f69e 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/ScanIssueStorage.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ScanIssueStorage.java @@ -59,7 +59,7 @@ public class ScanIssueStorage extends IssueStorage implements BatchComponent { long componentId = componentId(issue); long projectId = projectId(); int ruleId = ruleId(issue); - IssueDto dto = IssueDto.toDtoForInsert(issue, componentId, projectId, ruleId, now); + IssueDto dto = IssueDto.toDtoForBatchInsert(issue, componentId, projectId, ruleId, now); issueMapper.insert(dto); } diff --git a/sonar-core/src/main/java/org/sonar/core/component/AuthorizedComponentDto.java b/sonar-core/src/main/java/org/sonar/core/component/AuthorizedComponentDto.java index ee13722ce7c..668547c6928 100644 --- a/sonar-core/src/main/java/org/sonar/core/component/AuthorizedComponentDto.java +++ b/sonar-core/src/main/java/org/sonar/core/component/AuthorizedComponentDto.java @@ -22,8 +22,11 @@ package org.sonar.core.component; import org.sonar.core.persistence.Dto; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + /** - * Used to check that a project exists. Can return provisionned projects and projects from analysis. + * Used to check that a project exists. Can return provisioned projects and projects from analysis. * The root project id is not available because no join on snapshot is done to retrieve it. * * Warning, this component should not be retrieve from db using a join on snapshots, otherwise provisioned projects will not be returned anymore. @@ -31,6 +34,7 @@ import org.sonar.core.persistence.Dto; public class AuthorizedComponentDto extends Dto<String> { private Long id; + private String uuid; private String kee; private String scope; private String qualifier; @@ -44,6 +48,19 @@ public class AuthorizedComponentDto extends Dto<String> { return this; } + /** + * Can be null on a view or a developer + */ + @CheckForNull + public String uuid() { + return uuid; + } + + public AuthorizedComponentDto setAuthorizedUuid(@Nullable String uuid) { + this.uuid = uuid; + return this; + } + public String key() { return kee; } diff --git a/sonar-core/src/main/java/org/sonar/core/component/ComponentDto.java b/sonar-core/src/main/java/org/sonar/core/component/ComponentDto.java index 8d7914f56c1..026d959928e 100644 --- a/sonar-core/src/main/java/org/sonar/core/component/ComponentDto.java +++ b/sonar-core/src/main/java/org/sonar/core/component/ComponentDto.java @@ -28,7 +28,6 @@ import java.util.Date; public class ComponentDto extends AuthorizedComponentDto implements Component { - private String uuid; private String projectUuid; private String moduleUuid; private String moduleUuidPath; @@ -56,16 +55,8 @@ public class ComponentDto extends AuthorizedComponentDto implements Component { return this; } - /** - * Can be null on a view or a developer - */ - @CheckForNull - public String uuid() { - return uuid; - } - public ComponentDto setUuid(@Nullable String uuid) { - this.uuid = uuid; + super.setAuthorizedUuid(uuid); return this; } @@ -159,13 +150,19 @@ public class ComponentDto extends AuthorizedComponentDto implements Component { return this; } + /** + * @deprecated since 5.0, use projectUuid instead + */ + @Deprecated public Long projectId() { return projectId; } /** * Only for unit tests + * @deprecated since 5.0, use projectUuid instead */ + @Deprecated public ComponentDto setProjectId_unit_test_only(Long projectId) { this.projectId = projectId; return this; diff --git a/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java index 3ef31f6e61c..d62d7ac4c88 100644 --- a/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java @@ -33,12 +33,24 @@ import java.util.List; */ public interface ComponentMapper { + /** + * Warning, projectId is always null + */ @CheckForNull ComponentDto selectByKey(String key); + /** + * Warning, projectId is always null + */ @CheckForNull ComponentDto selectById(long id); + /** + * Warning, projectId is always null + */ + @CheckForNull + ComponentDto selectByUuid(String uuid); + @CheckForNull ComponentDto selectRootProjectByKey(String key); @@ -53,12 +65,17 @@ public interface ComponentMapper { /** * Return sub project of component keys */ - List<ComponentDto> findSubProjectsByComponentKeys(@Param("keys") Collection<String> keys); + List<ComponentDto> findSubProjectsByComponentUuids(@Param("uuids") Collection<String> uuids); List<ComponentDto> findByIds(@Param("ids") Collection<Long> ids); List<ComponentDto> findByKeys(@Param("keys") Collection<String> keys); + /** + * Warning, projectId are always null + */ + List<ComponentDto> findByUuids(@Param("uuids") Collection<String> uuids); + long countById(long id); @CheckForNull diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueAuthorizationDto.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueAuthorizationDto.java index 0c0b767c403..97d3a3bb413 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueAuthorizationDto.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueAuthorizationDto.java @@ -29,22 +29,22 @@ import static com.google.common.collect.Lists.newArrayList; public final class IssueAuthorizationDto extends Dto<String> implements Serializable { - private String project; + private String projectUuid; private String permission; private List<String> groups = newArrayList(); private List<String> users = newArrayList(); @Override public String getKey() { - return project; + return projectUuid; } - public String getProject() { - return project; + public String getProjectUuid() { + return projectUuid; } - public IssueAuthorizationDto setProject(String project) { - this.project = project; + public IssueAuthorizationDto setProjectUuid(String projectUuid) { + this.projectUuid = projectUuid; return this; } 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 550ce46b6d3..0687f0ea082 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 @@ -47,7 +47,7 @@ public final class IssueDto extends Dto<String> implements Serializable { private Long id; private String kee; private Long componentId; - private Long rootComponentId; + private Long projectId; private Integer ruleId; private String severity; private boolean manualSeverity; @@ -79,7 +79,11 @@ public final class IssueDto extends Dto<String> implements Serializable { private String ruleRepo; private String language; private String componentKey; - private String rootComponentKey; + private String componentUuid; + private String moduleUuid; + private String moduleUuidPath; + private String projectKey; + private String projectUuid; @Override public String getKey() { @@ -111,6 +115,9 @@ public final class IssueDto extends Dto<String> implements Serializable { public IssueDto setComponent(ComponentDto component) { this.componentId = component.getId(); this.componentKey = component.getKey(); + this.componentUuid = component.uuid(); + this.moduleUuid = component.moduleUuid(); + this.moduleUuidPath = component.moduleUuidPath(); return this; } @@ -122,21 +129,22 @@ public final class IssueDto extends Dto<String> implements Serializable { return this; } - public Long getRootComponentId() { - return rootComponentId; + public Long getProjectId() { + return projectId; } - public IssueDto setRootComponent(ComponentDto rootComponent) { - this.rootComponentId = rootComponent.getId(); - this.rootComponentKey = rootComponent.getKey(); + public IssueDto setProject(ComponentDto project) { + this.projectId = project.getId(); + this.projectKey = project.getKey(); + this.projectUuid = project.uuid(); return this; } /** - * please use setRootComponent + * please use setProject */ - public IssueDto setRootComponentId(Long rootComponentId) { - this.rootComponentId = rootComponentId; + public IssueDto setProjectId(Long projectId) { + this.projectId = projectId; return this; } @@ -357,8 +365,27 @@ public final class IssueDto extends Dto<String> implements Serializable { return componentKey; } - public String getRootComponentKey() { - return rootComponentKey; + public String getComponentUuid() { + return componentUuid; + } + + public String getModuleUuid() { + return moduleUuid; + } + + public String getModuleUuidPath() { + return moduleUuidPath; + } + + /** + * Used by the issue tracking mechanism, but it should used the component uuid instead + */ + public String getProjectKey() { + return projectKey; + } + + public String getProjectUuid() { + return projectUuid; } @CheckForNull @@ -405,10 +432,50 @@ 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 + * Please use {@link #setComponent(org.sonar.core.component.ComponentDto)} instead + */ + public IssueDto setComponentUuid(String componentUuid) { + this.componentUuid = componentUuid; + return this; + } + + /** + * Should only be used to persist in E/S + * + * Please use {@link #setComponent(org.sonar.core.component.ComponentDto)} instead */ - public IssueDto setRootComponentKey(String rootComponentKey) { - this.rootComponentKey = rootComponentKey; + public IssueDto setModuleUuid(String moduleUuid) { + this.moduleUuid = moduleUuid; + return this; + } + + /** + * Should only be used to persist in E/S + * + * Please use {@link #setComponent(org.sonar.core.component.ComponentDto)} instead + */ + public IssueDto setModuleUuidPath(String moduleUuidPath) { + this.moduleUuidPath = moduleUuidPath; + return this; + } + + /** + * Should only be used to persist in E/S + * + * Please use {@link #setProject(org.sonar.core.component.ComponentDto)} instead + */ + public IssueDto setProjectKey(String projectKey) { + this.projectKey = projectKey; + return this; + } + + /** + * Should only be used to persist in E/S + * + * Please use {@link #setProject(org.sonar.core.component.ComponentDto)} instead + */ + public IssueDto setProjectUuid(String projectUuid) { + this.projectUuid = projectUuid; return this; } @@ -417,7 +484,10 @@ public final class IssueDto extends Dto<String> implements Serializable { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); } - public static IssueDto toDtoForInsert(DefaultIssue issue, Long componentId, Long rootComponentId, Integer ruleId, Date now) { + /** + * On batch side, component keys and uuid are useless + */ + public static IssueDto toDtoForBatchInsert(DefaultIssue issue, Long componentId, Long rootComponentId, Integer ruleId, Date now) { return new IssueDto() .setKee(issue.key()) .setLine(issue.line()) @@ -433,10 +503,15 @@ public final class IssueDto extends Dto<String> implements Serializable { .setAssignee(issue.assignee()) .setRuleId(ruleId) .setRuleKey(issue.ruleKey().repository(), issue.ruleKey().rule()) + .setComponentUuid(issue.componentUuid()) .setComponentId(componentId) .setComponentKey(issue.componentKey()) - .setRootComponentId(rootComponentId) - .setRootComponentKey(issue.projectKey()) + .setModuleUuid(issue.moduleUuid()) + .setModuleUuidPath(issue.moduleUuidPath()) + .setComponentUuid(issue.componentUuid()) + .setProjectUuid(issue.projectUuid()) + .setProjectId(rootComponentId) + .setProjectKey(issue.projectKey()) .setActionPlanKey(issue.actionPlanKey()) .setIssueAttributes(KeyValueFormat.format(issue.attributes())) .setAuthorLogin(issue.authorLogin()) @@ -448,6 +523,15 @@ public final class IssueDto extends Dto<String> implements Serializable { .setUpdatedAt(now); } + /** + * On server side, we need component keys and uuid + */ + public static IssueDto toDtoForServerInsert(DefaultIssue issue, ComponentDto component, ComponentDto project, Integer ruleId, Date now) { + return toDtoForBatchInsert(issue, component.getId(), project.getId(), ruleId, now) + .setComponent(component) + .setProject(project); + } + public static IssueDto toDtoForUpdate(DefaultIssue issue, Long rootComponentId, Date now) { // Invariant fields, like key and rule, can't be updated return new IssueDto() @@ -467,9 +551,13 @@ public final class IssueDto extends Dto<String> implements Serializable { .setIssueAttributes(KeyValueFormat.format(issue.attributes())) .setAuthorLogin(issue.authorLogin()) .setRuleKey(issue.ruleKey().repository(), issue.ruleKey().rule()) + .setComponentUuid(issue.componentUuid()) .setComponentKey(issue.componentKey()) - .setRootComponentKey(issue.projectKey()) - .setRootComponentId(rootComponentId) + .setModuleUuid(issue.moduleUuid()) + .setModuleUuidPath(issue.moduleUuidPath()) + .setProjectUuid(issue.projectUuid()) + .setProjectKey(issue.projectKey()) + .setProjectId(rootComponentId) .setIssueCreationDate(issue.creationDate()) .setIssueCloseDate(issue.closeDate()) .setIssueUpdateDate(issue.updateDate()) @@ -492,7 +580,11 @@ public final class IssueDto extends Dto<String> implements Serializable { issue.setAttributes(KeyValueFormat.parse(Objects.firstNonNull(issueAttributes, ""))); issue.setComponentKey(componentKey); issue.setComponentId(componentId); - issue.setProjectKey(rootComponentKey); + issue.setComponentUuid(componentUuid); + issue.setModuleUuid(moduleUuid); + issue.setModuleUuidPath(moduleUuidPath); + issue.setProjectUuid(projectUuid); + issue.setProjectKey(projectKey); issue.setManualSeverity(manualSeverity); issue.setRuleKey(getRuleKey()); issue.setLanguage(language); @@ -508,7 +600,7 @@ public final class IssueDto extends Dto<String> implements Serializable { public static IssueDto createFor(Project project, RuleDto rule) { return new IssueDto() - .setRootComponentId(Long.valueOf(project.getId())) + .setProjectId(Long.valueOf(project.getId())) .setRuleId(rule.getId()) .setKee(UUID.randomUUID().toString()); } diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java b/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java index 883d85d9ea8..622de121842 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java @@ -41,7 +41,7 @@ public class UpdateConflictResolver { IssueDto dbIssue = mapper.selectByKey(issue.key()); if (dbIssue != null) { mergeFields(dbIssue, issue); - mapper.update(IssueDto.toDtoForUpdate(issue, dbIssue.getRootComponentId(), new Date())); + mapper.update(IssueDto.toDtoForUpdate(issue, dbIssue.getProjectId(), new Date())); } } diff --git a/sonar-core/src/main/java/org/sonar/core/user/AuthorizationDao.java b/sonar-core/src/main/java/org/sonar/core/user/AuthorizationDao.java index db7d9b128fb..6c73eade4e8 100644 --- a/sonar-core/src/main/java/org/sonar/core/user/AuthorizationDao.java +++ b/sonar-core/src/main/java/org/sonar/core/user/AuthorizationDao.java @@ -28,11 +28,7 @@ import org.sonar.core.persistence.MyBatis; import javax.annotation.Nullable; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import static com.google.common.collect.Maps.newHashMap; @@ -85,6 +81,16 @@ public class AuthorizationDao implements ServerComponent, DaoComponent { } } + public Collection<String> selectAuthorizedRootProjectsUuids(@Nullable Integer userId, String role) { + SqlSession session = mybatis.openSession(false); + try { + return selectAuthorizedRootProjectsUuids(userId, role, session); + + } finally { + MyBatis.closeQuietly(session); + } + } + public Collection<String> selectAuthorizedRootProjectsKeys(@Nullable Integer userId, String role, SqlSession session) { String sql; Map<String, Object> params = newHashMap(); @@ -95,6 +101,16 @@ public class AuthorizationDao implements ServerComponent, DaoComponent { return session.selectList(sql, params); } + public Collection<String> selectAuthorizedRootProjectsUuids(@Nullable Integer userId, String role, SqlSession session) { + String sql; + Map<String, Object> params = newHashMap(); + sql = "selectAuthorizedRootProjectsUuids"; + params.put("userId", userId); + params.put("role", role); + + return session.selectList(sql, params); + } + public List<String> selectGlobalPermissions(@Nullable String userLogin) { SqlSession session = mybatis.openSession(false); try { diff --git a/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml b/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml index ba0aabd0b4d..b2dfd9b20ba 100644 --- a/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml @@ -14,15 +14,36 @@ p.qualifier as qualifier, p.scope as scope, p.language as language, + p.root_id as subProjectId, + p.path as path, + p.enabled as enabled, + p.authorization_updated_at as authorizationUpdatedAt, + p.created_at as createdAt + </sql> + + <sql id="oldComponentColumns"> + p.id, + p.uuid as uuid, + p.project_uuid as projectUuid, + p.module_uuid as moduleUuid, + p.module_uuid_path as moduleUuidPath, + p.kee as kee, + p.name as name, + p.long_name as longName, + p.qualifier as qualifier, + p.scope as scope, + p.language as language, s.root_project_id as projectId, p.root_id as subProjectId, p.path as path, + p.enabled as enabled, p.authorization_updated_at as authorizationUpdatedAt, p.created_at as createdAt </sql> <sql id="authorizedComponentColumns"> p.id, + p.uuid as uuid, p.kee as kee, p.qualifier as qualifier, p.scope as scope @@ -31,9 +52,7 @@ <select id="selectByKey" parameterType="String" resultType="Component"> SELECT <include refid="componentColumns"/> FROM projects p - INNER JOIN snapshots s ON s.project_id=p.id AND s.islast=${_true} <where> - AND p.enabled=${_true} AND p.kee=#{key} </where> </select> @@ -41,18 +60,23 @@ <select id="selectById" parameterType="long" resultType="Component"> SELECT <include refid="componentColumns"/> FROM projects p - INNER JOIN snapshots s ON s.project_id=p.id AND s.islast=${_true} <where> - AND p.enabled=${_true} AND p.id=#{id} </where> </select> + <select id="selectByUuid" parameterType="String" resultType="Component"> + SELECT <include refid="componentColumns"/> + FROM projects p + <where> + AND p.uuid=#{uuid} + </where> + </select> + <select id="countById" parameterType="long" resultType="long"> SELECT count(p.id) FROM projects p <where> - AND p.enabled=${_true} AND p.id=#{id} </where> </select> @@ -68,7 +92,7 @@ </select> <select id="selectParentModuleByKey" parameterType="String" resultType="Component"> - SELECT <include refid="componentColumns"/> + SELECT <include refid="oldComponentColumns"/> FROM projects p INNER JOIN snapshots s ON s.project_id=p.id AND s.islast=${_true} INNER JOIN snapshots child_snapshots ON child_snapshots.parent_snapshot_id=s.id AND s.islast=${_true} @@ -80,7 +104,7 @@ </select> <select id="findModulesByProject" parameterType="String" resultType="Component"> - SELECT <include refid="componentColumns"/> + SELECT <include refid="oldComponentColumns"/> FROM projects p INNER JOIN snapshots s ON s.project_id=p.id AND s.islast=${_true} INNER JOIN snapshots parent_snapshots ON parent_snapshots.id=s.parent_snapshot_id AND s.islast=${_true} @@ -92,7 +116,7 @@ </select> <select id="findByIds" parameterType="long" resultType="Component"> - select <include refid="componentColumns"/> + select <include refid="oldComponentColumns"/> from projects p inner join snapshots s on s.project_id=p.id and s.islast=${_true} <where> @@ -105,7 +129,7 @@ </select> <select id="findByKeys" parameterType="String" resultType="Component"> - select <include refid="componentColumns"/> + select <include refid="oldComponentColumns"/> from projects p inner join snapshots s on s.project_id=p.id and s.islast=${_true} <where> @@ -117,17 +141,28 @@ </where> </select> - <select id="findSubProjectsByComponentKeys" parameterType="String" resultType="Component"> - SELECT <include refid="componentColumns"/> + <select id="findByUuids" parameterType="String" resultType="Component"> + select <include refid="componentColumns"/> + from projects p + <where> + and p.uuid in + <foreach collection="uuids" open="(" close=")" item="uuid" separator=","> + #{uuid} + </foreach> + </where> + </select> + + <select id="findSubProjectsByComponentUuids" parameterType="String" resultType="Component"> + SELECT <include refid="oldComponentColumns"/> FROM projects p INNER JOIN snapshots s ON s.project_id=p.id AND s.islast=${_true} INNER JOIN projects child ON child.root_id=p.id AND child.enabled=${_true} <where> AND p.enabled=${_true} AND p.scope='PRJ' - AND child.kee in - <foreach collection="keys" open="(" close=")" item="key" separator=","> - #{key} + AND child.uuid in + <foreach collection="uuids" open="(" close=")" item="uuid" separator=","> + #{uuid} </foreach> </where> </select> @@ -151,12 +186,12 @@ </select> <sql id="insertColumns"> - (kee, uuid, project_uuid, module_uuid, module_uuid_path, name, long_name, qualifier, scope, language, root_id, path, created_at, authorization_updated_at) + (kee, uuid, project_uuid, module_uuid, module_uuid_path, name, long_name, qualifier, scope, language, root_id, path, enabled, created_at, authorization_updated_at) </sql> <insert id="insert" parameterType="Component" keyColumn="id" useGeneratedKeys="true" keyProperty="id"> insert into projects <include refid="insertColumns"/> - values (#{kee}, #{uuid}, #{projectUuid}, #{moduleUuid}, #{moduleUuidPath}, #{name}, #{longName}, #{qualifier}, #{scope}, #{language}, #{subProjectId}, #{path}, #{createdAt}, #{authorizationUpdatedAt}) + values (#{kee}, #{uuid}, #{projectUuid}, #{moduleUuid}, #{moduleUuidPath}, #{name}, #{longName}, #{qualifier}, #{scope}, #{language}, #{subProjectId}, #{path}, #{enabled}, #{createdAt}, #{authorizationUpdatedAt}) </insert> <delete id="deleteByKey" parameterType="String"> diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueAuthorizationMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueAuthorizationMapper.xml index 5a1f44d6c62..2a7b3ecb06d 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueAuthorizationMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueAuthorizationMapper.xml @@ -22,7 +22,7 @@ FROM ( -- users SELECT - projects.kee AS project, + projects.uuid AS project, projects.authorization_updated_at AS updated_at, users.login AS login, NULL AS permission_group, @@ -31,14 +31,14 @@ INNER JOIN user_roles ON user_roles.resource_id = projects.id AND user_roles.role = #{permission} INNER JOIN users ON users.id = user_roles.user_id WHERE - projects.authorization_updated_at >= #{date} + projects.authorization_updated_at >= #{date} <if test="project != null"> - and projects.kee = #{project} + and projects.uuid = #{project} </if> UNION -- groups without Anyone SELECT - projects.kee AS project, + projects.uuid AS project, projects.authorization_updated_at AS updated_at, NULL AS login, groups.name AS permission_group, @@ -49,13 +49,13 @@ WHERE projects.authorization_updated_at >= #{date} <if test="project != null"> - and projects.kee = #{project} + and projects.uuid = #{project} </if> AND group_id IS NOT NULL UNION -- Anyone groups SELECT - projects.kee AS project, + projects.uuid AS project, projects.authorization_updated_at AS updated_at, NULL AS login, #{anyone} AS permission_group, @@ -65,7 +65,7 @@ WHERE projects.authorization_updated_at >= #{date} <if test="project != null"> - and projects.kee = #{project} + and projects.uuid = #{project} </if> AND group_roles.group_id IS NULL ) project_authorization diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml index ba581165538..0fe245154a1 100644 --- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml @@ -8,7 +8,7 @@ i.id, i.kee as kee, i.component_id as componentId, - i.root_component_id as rootComponentId, + i.root_component_id as projectId, i.rule_id as ruleId, i.action_plan_key as actionPlanKey, i.severity as severity, @@ -33,7 +33,11 @@ r.plugin_name as ruleRepo, r.language as language, p.kee as componentKey, - root.kee as rootComponentKey + p.uuid as componentUuid, + p.module_uuid as moduleUuid, + p.module_uuid_path as moduleUuidPath, + root.kee as projectKey, + root.uuid as projectUuid </sql> <sql id="sortColumn"> @@ -66,7 +70,7 @@ message, line, effort_to_fix, technical_debt, status, resolution, checksum, reporter, assignee, author_login, issue_attributes, issue_creation_date, issue_update_date, issue_close_date, created_at, updated_at) - VALUES (#{kee}, #{componentId}, #{rootComponentId}, #{ruleId}, #{actionPlanKey}, #{severity}, #{manualSeverity}, + VALUES (#{kee}, #{componentId}, #{projectId}, #{ruleId}, #{actionPlanKey}, #{severity}, #{manualSeverity}, #{message}, #{line}, #{effortToFix}, #{debt}, #{status}, #{resolution}, #{checksum}, #{reporter}, #{assignee}, #{authorLogin}, #{issueAttributes}, #{issueCreationDate}, #{issueUpdateDate}, #{issueCloseDate}, #{createdAt}, #{updatedAt}) @@ -90,7 +94,7 @@ reporter=#{reporter}, assignee=#{assignee}, author_login=#{authorLogin}, - root_component_id=#{rootComponentId}, + root_component_id=#{projectId}, issue_attributes=#{issueAttributes}, issue_creation_date=#{issueCreationDate}, issue_update_date=#{issueUpdateDate}, @@ -117,7 +121,7 @@ reporter=#{reporter}, assignee=#{assignee}, author_login=#{authorLogin}, - root_component_id=#{rootComponentId}, + root_component_id=#{projectId}, issue_attributes=#{issueAttributes}, issue_creation_date=#{issueCreationDate}, issue_update_date=#{issueUpdateDate}, @@ -158,7 +162,7 @@ i.id, i.kee as kee, i.component_id as componentId, - i.root_component_id as rootComponentId, + i.root_component_id as projectId, i.rule_id as ruleId, i.action_plan_key as actionPlanKey, i.severity as severity, @@ -182,7 +186,7 @@ r.plugin_rule_key as ruleKey, r.plugin_name as ruleRepo, p.kee as componentKey, - root.kee as rootComponentKey + root.kee as projectKey from issues i inner join (select p.id,p.kee from projects p where (p.root_id=#{id} and p.qualifier <> 'BRC') or (p.id=#{id})) p on p.id=i.component_id diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl index 67b1937b9d2..44e8a600fee 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/schema-h2.ddl @@ -469,6 +469,7 @@ CREATE TABLE "ISSUES" ( "ISSUE_UPDATE_DATE" TIMESTAMP, "CREATED_AT" TIMESTAMP, "UPDATED_AT" TIMESTAMP + ); CREATE TABLE "ISSUE_CHANGES" ( diff --git a/sonar-core/src/main/resources/org/sonar/core/user/AuthorizationMapper.xml b/sonar-core/src/main/resources/org/sonar/core/user/AuthorizationMapper.xml index 79c15536960..88549a4ab31 100644 --- a/sonar-core/src/main/resources/org/sonar/core/user/AuthorizationMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/user/AuthorizationMapper.xml @@ -65,6 +65,37 @@ </choose> </sql> + <select id="selectAuthorizedRootProjectsUuids" parameterType="map" resultType="string"> + <choose> + <when test="userId != null"> + SELECT p.uuid as root_project_uuid + FROM group_roles gr + INNER JOIN projects p on p.id = gr.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + <where> + and gr.role=#{role} + and (gr.group_id is null or gr.group_id in (select gu.group_id from groups_users gu where gu.user_id=#{userId})) + </where> + UNION + SELECT p.uuid as root_project_uuid + FROM user_roles ur + INNER JOIN projects p on p.id = ur.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + <where> + and ur.role=#{role} + and ur.user_id = #{userId} + </where> + </when> + <otherwise> + SELECT p.uuid as root_project_uuid + FROM group_roles gr + INNER JOIN projects p on p.id = gr.resource_id AND p.scope = 'PRJ' AND p.qualifier = 'TRK' + <where> + and gr.role=#{role} + and gr.group_id is null + </where> + </otherwise> + </choose> + </select> + <!-- same as selectAuthorizedRootProjectsKeysQuery but returns ids instead of keys --> <sql id="selectAuthorizedRootProjectIdsQuery"> <choose> diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueAuthorizationDtoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueAuthorizationDtoTest.java index ec21f118258..22b7e4943a8 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueAuthorizationDtoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueAuthorizationDtoTest.java @@ -30,13 +30,13 @@ public class IssueAuthorizationDtoTest { @Test public void getter_and_setter() throws Exception { IssueAuthorizationDto dto = new IssueAuthorizationDto() - .setProject("Sample") + .setProjectUuid("Sample") .setPermission("user") .setGroups(newArrayList("sonar-users")) .setUsers(newArrayList("john")); assertThat(dto.getKey()).isEqualTo("Sample"); - assertThat(dto.getProject()).isEqualTo("Sample"); + assertThat(dto.getProjectUuid()).isEqualTo("Sample"); assertThat(dto.getPermission()).isEqualTo("user"); assertThat(dto.getGroups()).containsExactly("sonar-users"); assertThat(dto.getUsers()).containsExactly("john"); @@ -45,7 +45,7 @@ public class IssueAuthorizationDtoTest { @Test public void add_group() throws Exception { IssueAuthorizationDto dto = new IssueAuthorizationDto() - .setProject("Sample") + .setProjectUuid("Sample") .setPermission("user") .setGroups(newArrayList("sonar-users")) .setUsers(newArrayList("john")); @@ -60,7 +60,7 @@ public class IssueAuthorizationDtoTest { @Test public void add_user() throws Exception { IssueAuthorizationDto dto = new IssueAuthorizationDto() - .setProject("Sample") + .setProjectUuid("Sample") .setPermission("user") .setGroups(newArrayList("sonar-users")) .setUsers(newArrayList("john")); diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java index cf49a133424..cdc28b07b26 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java @@ -55,8 +55,6 @@ public class IssueDaoTest extends AbstractDaoTestCase { IssueDto issue = dao.selectByKey("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(); @@ -77,8 +75,14 @@ public class IssueDaoTest extends AbstractDaoTestCase { assertThat(issue.getUpdatedAt()).isNotNull(); assertThat(issue.getRuleRepo()).isEqualTo("squid"); assertThat(issue.getRule()).isEqualTo("AvoidCycle"); + assertThat(issue.getComponentUuid()).isEqualTo("CDEF"); assertThat(issue.getComponentKey()).isEqualTo("Action.java"); - assertThat(issue.getRootComponentKey()).isEqualTo("struts"); + assertThat(issue.getComponentId()).isEqualTo(401); + assertThat(issue.getModuleUuid()).isEqualTo("BCDE"); + assertThat(issue.getModuleUuidPath()).isEqualTo("ABCD.BCDE."); + assertThat(issue.getProjectKey()).isEqualTo("struts"); // ABCD + assertThat(issue.getProjectUuid()).isEqualTo("ABCD"); // null + assertThat(issue.getProjectId()).isEqualTo(399); } @Test @@ -94,7 +98,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { assertThat(issue.getRuleRepo()).isNotNull(); assertThat(issue.getRule()).isNotNull(); assertThat(issue.getComponentKey()).isNotNull(); - assertThat(issue.getRootComponentKey()).isEqualTo("struts"); + assertThat(issue.getProjectKey()).isEqualTo("struts"); // 399 is the root module, we should only find 1 issue on itself handler = new DefaultResultHandler(); @@ -103,7 +107,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { issue = (IssueDto) handler.getResultList().get(0); assertThat(issue.getComponentKey()).isEqualTo("struts"); - assertThat(issue.getRootComponentKey()).isEqualTo("struts"); + assertThat(issue.getProjectKey()).isEqualTo("struts"); } /** @@ -124,7 +128,7 @@ public class IssueDaoTest extends AbstractDaoTestCase { assertThat(issue.getRuleRepo()).isNotNull(); assertThat(issue.getRule()).isNotNull(); assertThat(issue.getComponentKey()).isNotNull(); - assertThat(issue.getRootComponentKey()).isNull(); + assertThat(issue.getProjectKey()).isNull(); } @Test diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java index 5b9abf13033..829b1f22ba2 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDtoTest.java @@ -62,9 +62,13 @@ public class IssueDtoTest { .setRuleKey("squid", "AvoidCycle") .setLanguage("xoo") .setComponentKey("org.sonar.sample:Sample") - .setRootComponentKey("org.sonar.sample") + .setComponentUuid("CDEF") + .setModuleUuid("BCDE") + .setModuleUuidPath("ABCD.BCDE.") + .setProjectUuid("ABCD") + .setProjectKey("org.sonar.sample") .setComponentId(1l) - .setRootComponentId(1l) + .setProjectId(1l) .setStatus(Issue.STATUS_CLOSED) .setResolution(Issue.RESOLUTION_FALSE_POSITIVE) .setEffortToFix(15.0) @@ -85,8 +89,12 @@ public class IssueDtoTest { assertThat(issue.key()).isEqualTo("100"); assertThat(issue.ruleKey().toString()).isEqualTo("squid:AvoidCycle"); assertThat(issue.language()).isEqualTo("xoo"); + assertThat(issue.componentUuid()).isEqualTo("CDEF"); assertThat(issue.componentKey()).isEqualTo("org.sonar.sample:Sample"); assertThat(issue.componentId()).isEqualTo(1L); + assertThat(issue.moduleUuid()).isEqualTo("BCDE"); + assertThat(issue.moduleUuidPath()).isEqualTo("ABCD.BCDE."); + assertThat(issue.projectUuid()).isEqualTo("ABCD"); assertThat(issue.projectKey()).isEqualTo("org.sonar.sample"); assertThat(issue.status()).isEqualTo(Issue.STATUS_CLOSED); assertThat(issue.resolution()).isEqualTo(Issue.RESOLUTION_FALSE_POSITIVE); diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java index 705c5358ea8..eda114c938f 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java @@ -49,7 +49,7 @@ public class IssueMapperTest extends AbstractDaoTestCase { public void testInsert() throws Exception { IssueDto dto = new IssueDto(); dto.setComponentId(123l); - dto.setRootComponentId(100l); + dto.setProjectId(100l); dto.setRuleId(200); dto.setKee("ABCDE"); dto.setLine(500); @@ -84,7 +84,7 @@ public class IssueMapperTest extends AbstractDaoTestCase { IssueDto dto = new IssueDto(); dto.setComponentId(123l); - dto.setRootComponentId(101l); + dto.setProjectId(101l); dto.setRuleId(200); dto.setKee("ABCDE"); dto.setLine(500); @@ -119,7 +119,7 @@ public class IssueMapperTest extends AbstractDaoTestCase { IssueDto dto = new IssueDto(); dto.setComponentId(123l); - dto.setRootComponentId(101l); + dto.setProjectId(101l); dto.setRuleId(200); dto.setKee("ABCDE"); dto.setLine(500); @@ -157,7 +157,7 @@ public class IssueMapperTest extends AbstractDaoTestCase { IssueDto dto = new IssueDto(); dto.setComponentId(123l); - dto.setRootComponentId(101l); + dto.setProjectId(101l); dto.setRuleId(200); dto.setKee("ABCDE"); dto.setLine(500); diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStorageTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStorageTest.java index 8231ddaced9..59ed7c49e40 100644 --- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStorageTest.java +++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueStorageTest.java @@ -31,6 +31,7 @@ import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.RuleQuery; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.Duration; +import org.sonar.core.component.ComponentDto; import org.sonar.core.persistence.AbstractDaoTestCase; import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; @@ -55,8 +56,8 @@ public class IssueStorageTest extends AbstractDaoTestCase { } @Test - public void insert_new_issues() throws Exception { - FakeSaver saver = new FakeSaver(getMyBatis(), new FakeRuleFinder()); + public void batch_insert_new_issues() throws Exception { + FakeBatchSaver saver = new FakeBatchSaver(getMyBatis(), new FakeRuleFinder()); DefaultIssueComment comment = DefaultIssueComment.create("ABCDE", "emmerik", "the comment"); // override generated key @@ -88,8 +89,8 @@ public class IssueStorageTest extends AbstractDaoTestCase { } @Test - public void insert_new_issues_with_session() throws Exception { - FakeSaver saver = new FakeSaver(getMyBatis(), new FakeRuleFinder()); + public void batch_insert_new_issues_with_session() throws Exception { + FakeBatchSaver saver = new FakeBatchSaver(getMyBatis(), new FakeRuleFinder()); DefaultIssueComment comment = DefaultIssueComment.create("ABCDE", "emmerik", "the comment"); // override generated key @@ -122,10 +123,90 @@ public class IssueStorageTest extends AbstractDaoTestCase { } @Test - public void update_issues() throws Exception { + public void server_insert_new_issues_with_session() throws Exception { + ComponentDto project = new ComponentDto().setId(10L); + ComponentDto component = new ComponentDto().setId(100L); + FakeServerSaver saver = new FakeServerSaver(getMyBatis(), new FakeRuleFinder(), component, project); + + DefaultIssueComment comment = DefaultIssueComment.create("ABCDE", "emmerik", "the comment"); + // override generated key + comment.setKey("FGHIJ"); + + Date date = DateUtils.parseDate("2013-05-18"); + DefaultIssue issue = new DefaultIssue() + .setKey("ABCDE") + .setNew(true) + + .setRuleKey(RuleKey.of("squid", "AvoidCycle")) + .setLine(5000) + .setDebt(Duration.create(10L)) + .setReporter("emmerik") + .setResolution("OPEN") + .setStatus("OPEN") + .setSeverity("BLOCKER") + .setAttribute("foo", "bar") + .addComment(comment) + .setCreationDate(date) + .setUpdateDate(date) + .setCloseDate(date) + + .setComponentKey("struts:Action"); + + saver.save(session, issue); + session.commit(); + + checkTables("should_insert_new_issues", new String[]{"id", "created_at", "updated_at", "issue_change_creation_date"}, "issues", "issue_changes"); + } + + @Test + public void batch_update_issues() throws Exception { + setupData("should_update_issues"); + + FakeBatchSaver saver = new FakeBatchSaver(getMyBatis(), new FakeRuleFinder()); + + DefaultIssueComment comment = DefaultIssueComment.create("ABCDE", "emmerik", "the comment"); + // override generated key + comment.setKey("FGHIJ"); + + Date date = DateUtils.parseDate("2013-05-18"); + DefaultIssue issue = new DefaultIssue() + .setKey("ABCDE") + .setNew(false) + .setChanged(true) + + // updated fields + .setLine(5000) + .setDebt(Duration.create(10L)) + .setChecksum("FFFFF") + .setAuthorLogin("simon") + .setAssignee("loic") + .setFieldChange(context, "severity", "INFO", "BLOCKER") + .setReporter("emmerik") + .setResolution("FIXED") + .setStatus("RESOLVED") + .setSeverity("BLOCKER") + .setAttribute("foo", "bar") + .addComment(comment) + .setCreationDate(date) + .setUpdateDate(date) + .setCloseDate(date) + + // unmodifiable fields + .setRuleKey(RuleKey.of("xxx", "unknown")) + .setComponentKey("not:a:component"); + + saver.save(issue); + + checkTables("should_update_issues", new String[]{"id", "created_at", "updated_at", "issue_change_creation_date"}, "issues", "issue_changes"); + } + + @Test + public void server_update_issues() throws Exception { setupData("should_update_issues"); - FakeSaver saver = new FakeSaver(getMyBatis(), new FakeRuleFinder()); + ComponentDto project = new ComponentDto().setId(10L); + ComponentDto component = new ComponentDto().setId(100L); + FakeServerSaver saver = new FakeServerSaver(getMyBatis(), new FakeRuleFinder(), component, project); DefaultIssueComment comment = DefaultIssueComment.create("ABCDE", "emmerik", "the comment"); // override generated key @@ -163,16 +244,42 @@ public class IssueStorageTest extends AbstractDaoTestCase { checkTables("should_update_issues", new String[]{"id", "created_at", "updated_at", "issue_change_creation_date"}, "issues", "issue_changes"); } - static class FakeSaver extends IssueStorage { + static class FakeBatchSaver extends IssueStorage { + + protected FakeBatchSaver(MyBatis mybatis, RuleFinder ruleFinder) { + super(mybatis, ruleFinder); + } + + @Override + protected void doInsert(DbSession session, Date now, DefaultIssue issue) { + int ruleId = ruleId(issue); + IssueDto dto = IssueDto.toDtoForBatchInsert(issue, 100l, 10l, ruleId, now); + + session.getMapper(IssueMapper.class).insert(dto); + } + + @Override + protected void doUpdate(DbSession session, Date now, DefaultIssue issue) { + IssueDto dto = IssueDto.toDtoForUpdate(issue, 10l, now); + session.getMapper(IssueMapper.class).update(dto); + } + } + + static class FakeServerSaver extends IssueStorage { + + private final ComponentDto component; + private final ComponentDto project; - protected FakeSaver(MyBatis mybatis, RuleFinder ruleFinder) { + protected FakeServerSaver(MyBatis mybatis, RuleFinder ruleFinder, ComponentDto component, ComponentDto project) { super(mybatis, ruleFinder); + this.component = component; + this.project = project; } @Override protected void doInsert(DbSession session, Date now, DefaultIssue issue) { int ruleId = ruleId(issue); - IssueDto dto = IssueDto.toDtoForInsert(issue, 100l, 10l, ruleId, now); + IssueDto dto = IssueDto.toDtoForServerInsert(issue, component, project, ruleId, now); session.getMapper(IssueMapper.class).insert(dto); } diff --git a/sonar-core/src/test/java/org/sonar/core/user/AuthorizationDaoTest.java b/sonar-core/src/test/java/org/sonar/core/user/AuthorizationDaoTest.java index a20f0b08ff8..594256cc85b 100644 --- a/sonar-core/src/test/java/org/sonar/core/user/AuthorizationDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/user/AuthorizationDaoTest.java @@ -153,6 +153,49 @@ public class AuthorizationDaoTest extends AbstractDaoTestCase { } @Test + public void should_return_root_project_uuids_for_user() { + setupData("should_return_root_project_keys_for_user"); + + AuthorizationDao authorization = new AuthorizationDao(getMyBatis()); + Collection<String> rootProjectUuids = authorization.selectAuthorizedRootProjectsUuids(USER, "user"); + + assertThat(rootProjectUuids).containsOnly("ABCD"); + + // user does not have the role "admin" + rootProjectUuids = authorization.selectAuthorizedRootProjectsKeys(USER, "admin"); + assertThat(rootProjectUuids).isEmpty(); + } + + @Test + public void should_return_root_project_uuids_for_group() { + // but user is not in an authorized group + setupData("should_return_root_project_keys_for_group"); + + AuthorizationDao authorization = new AuthorizationDao(getMyBatis()); + Collection<String> rootProjectUuids = authorization.selectAuthorizedRootProjectsUuids(USER, "user"); + + assertThat(rootProjectUuids).containsOnly("ABCD"); + + // user does not have the role "admin" + rootProjectUuids = authorization.selectAuthorizedRootProjectsKeys(USER, "admin"); + assertThat(rootProjectUuids).isEmpty(); + } + + @Test + public void should_return_root_project_uuids_for_anonymous() { + setupData("should_return_root_project_keys_for_anonymous"); + + AuthorizationDao authorization = new AuthorizationDao(getMyBatis()); + Collection<String> rootProjectUuids = authorization.selectAuthorizedRootProjectsUuids(null, "user"); + + assertThat(rootProjectUuids).containsOnly("ABCD"); + + // group does not have the role "admin" + rootProjectUuids = authorization.selectAuthorizedRootProjectsKeys(null, "admin"); + assertThat(rootProjectUuids).isEmpty(); + } + + @Test public void should_return_user_global_permissions() { setupData("should_return_user_global_permissions"); diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/shared.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/shared.xml index fe24d237d6b..a1606ab58d7 100644 --- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/shared.xml +++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/shared.xml @@ -2,10 +2,10 @@ <group_roles id="1" group_id="[null]" resource_id="399" role="user"/> - <projects id="399" kee="struts" root_id="[null]" qualifier="TRK" scope="PRJ" /> - <projects id="400" kee="struts-core" root_id="399" qualifier="BRC" scope="PRJ" /> - <projects id="401" kee="Action.java" root_id="400" qualifier="CLA" scope="PRJ" /> - <projects id="402" kee="Filter.java" root_id="400" qualifier="CLA" scope="PRJ" /> + <projects id="399" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="[null]" kee="struts" root_id="[null]" qualifier="TRK" scope="PRJ" /> + <projects id="400" uuid="BCDE" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="ABCD." kee="struts-core" root_id="399" qualifier="BRC" scope="PRJ" /> + <projects id="401" uuid="CDEF" project_uuid="ABCD" module_uuid="BCDE" module_uuid_path="ABCD.BCDE." kee="Action.java" root_id="400" qualifier="CLA" scope="PRJ" /> + <projects id="402" uuid="DEFG" project_uuid="ABCD" module_uuid="BCDE" module_uuid_path="ABCD.BCDE." kee="Filter.java" root_id="400" qualifier="CLA" scope="PRJ" /> <snapshots id="100" project_id="399" root_snapshot_id="[null]" parent_snapshot_id="[null]" root_project_id="399" path="" islast="[true]" /> <snapshots id="101" project_id="400" root_snapshot_id="100" parent_snapshot_id="100" root_project_id="399" path="100." islast="[true]" /> diff --git a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml index 14f78bec9ec..eb7321ec20f 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_anonymous.xml @@ -4,10 +4,10 @@ <groups_users user_id="100" group_id="200"/> <group_roles id="1" group_id="[null]" resource_id="300" role="user"/> - <projects id="300" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="301" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="302" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="300" uuid="ABCD" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="301" uuid="BCDE" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="302" uuid="CDEF" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="303" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="303" uuid="DEFG" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml index 9c5f753751d..05bca26378a 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_group.xml @@ -6,10 +6,10 @@ <groups_users user_id="100" group_id="200"/> <group_roles id="1" group_id="200" resource_id="300" role="user"/> - <projects id="300" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="301" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="302" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="300" uuid="ABCD" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="301" uuid="BCDE" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="302" uuid="CDEF" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="303" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="303" uuid="DEFG" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> </dataset> diff --git a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml index 773dd296f08..9ca62ae7ab8 100644 --- a/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml +++ b/sonar-core/src/test/resources/org/sonar/core/user/AuthorizationDaoTest/should_return_root_project_keys_for_user.xml @@ -5,10 +5,10 @@ <groups_users user_id="100" group_id="200"/> <group_roles id="1" group_id="200" resource_id="999" role="user"/> - <projects id="300" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="301" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="302" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="300" uuid="ABCD" kee="pj-w-snapshot" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="301" uuid="BCDE" kee="pj-w-snapshot1" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="302" uuid="CDEF" kee="pj-w-snapshot2" scope="PRJ" qualifier="TRK" enabled="[true]"/> - <projects id="303" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> + <projects id="303" uuid="DEFG" kee="pj-w-snapshot3" scope="PRJ" qualifier="TRK" enabled="[true]"/> </dataset> diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java index 44c8b456fd3..9bc6322ea1b 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java @@ -185,4 +185,14 @@ public interface Issue extends Serializable { * @since 5.0 */ String projectKey(); + + /** + * @since 5.0 + */ + String projectUuid(); + + /** + * @since 5.0 + */ + String componentUuid(); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java index ab5f23e203a..4e578681754 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/internal/DefaultIssue.java @@ -51,9 +51,17 @@ import static com.google.common.collect.Lists.newArrayList; public class DefaultIssue implements Issue { private String key; + + private String componentUuid; private String componentKey; private Long componentId; + + private String moduleUuid; + private String moduleUuidPath; + + private String projectUuid; private String projectKey; + private RuleKey ruleKey; private String language; private String severity; @@ -114,6 +122,16 @@ public class DefaultIssue implements Issue { } @Override + public String componentUuid() { + return componentUuid; + } + + public DefaultIssue setComponentUuid(String componentUuid) { + this.componentUuid = componentUuid; + return this; + } + + @Override public String componentKey() { return componentKey; } @@ -136,6 +154,36 @@ public class DefaultIssue implements Issue { return this; } + @CheckForNull + public String moduleUuid() { + return moduleUuid; + } + + public DefaultIssue setModuleUuid(@Nullable String moduleUuid) { + this.moduleUuid = moduleUuid; + return this; + } + + @CheckForNull + public String moduleUuidPath() { + return moduleUuidPath; + } + + public DefaultIssue setModuleUuidPath(@Nullable String moduleUuidPath) { + this.moduleUuidPath = moduleUuidPath; + return this; + } + + @Override + public String projectUuid() { + return projectUuid; + } + + public DefaultIssue setProjectUuid(String projectUuid) { + this.projectUuid = projectUuid; + return this; + } + @Override public String projectKey() { return projectKey; |