From d34d8266bc155988ecd9103b0cc6594399d63306 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Thu, 22 Jan 2015 16:51:15 +0100 Subject: [PATCH] SONAR-6013 Return manual rules in /batch/project to be able to handle manual issues --- .../server/batch/ProjectRepositoryAction.java | 1 + .../server/batch/ProjectRepositoryLoader.java | 81 ++++++++++++------- .../server/component/db/ComponentDao.java | 22 ----- .../org/sonar/server/issue/IssueService.java | 4 +- .../ProjectRepositoryLoaderMediumTest.java | 62 +++++--------- .../server/component/db/ComponentDaoTest.java | 40 --------- .../org/sonar/server/rule/RuleTesting.java | 2 +- .../core/component/db/ComponentMapper.java | 6 -- .../core/component/db/ComponentMapper.xml | 21 ----- 9 files changed, 79 insertions(+), 160 deletions(-) diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryAction.java index dd7d45c2d78..9f87aa9ad1f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryAction.java @@ -74,4 +74,5 @@ public class ProjectRepositoryAction implements RequestHandler { response.stream().setMediaType(MimeTypes.JSON); IOUtils.write(ref.toJson(), response.stream().output()); } + } diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java index 61917a48193..90d0151b79c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java @@ -26,6 +26,7 @@ import com.google.common.collect.Multimap; import org.sonar.api.ServerComponent; import org.sonar.api.resources.Language; import org.sonar.api.resources.Languages; +import org.sonar.api.rule.RuleKey; import org.sonar.batch.protocol.input.FileData; import org.sonar.batch.protocol.input.ProjectReferentials; import org.sonar.core.UtcDateUtils; @@ -43,11 +44,16 @@ import org.sonar.server.qualityprofile.QProfileFactory; import org.sonar.server.qualityprofile.QProfileLoader; import org.sonar.server.rule.Rule; import org.sonar.server.rule.RuleService; +import org.sonar.server.rule.index.RuleNormalizer; +import org.sonar.server.rule.index.RuleQuery; +import org.sonar.server.search.QueryContext; +import org.sonar.server.search.Result; import org.sonar.server.user.UserSession; import javax.annotation.Nullable; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; @@ -82,41 +88,43 @@ public class ProjectRepositoryLoader implements ServerComponent { ComponentDto module = dbClient.componentDao().getNullableByKey(session, query.getModuleKey()); // Current project/module can be null when analysing a new project if (module != null) { - ComponentDto project = dbClient.componentDao().getNullableRootProjectByKey(query.getModuleKey(), session); - - // Can be null if the given project is a provisioned one - if (project != null) { - if (!project.key().equals(module.key())) { - addSettings(ref, module.getKey(), getSettingsFromParents(module.key(), hasScanPerm, session)); - projectKey = project.key(); - } - - List moduleChildren = dbClient.componentDao().findChildrenModulesFromModule(session, query.getModuleKey()); - Map moduleUuidsByKey = moduleUuidsByKey(module, moduleChildren); - Map moduleIdsByKey = moduleIdsByKey(module, moduleChildren); - - List moduleChildrenSettings = dbClient.propertiesDao().findChildrenModuleProperties(query.getModuleKey(), session); - TreeModuleSettings treeModuleSettings = new TreeModuleSettings(moduleUuidsByKey, moduleIdsByKey, moduleChildren, moduleChildrenSettings, module); - - addSettingsToChildrenModules(ref, query.getModuleKey(), Maps.newHashMap(), treeModuleSettings, hasScanPerm, session); - addFileData(session, ref, moduleChildren, module.key()); - } else { - // Add settings of the provisioned project - addSettings(ref, query.getModuleKey(), getPropertiesMap(dbClient.propertiesDao().selectProjectProperties(query.getModuleKey(), session), hasScanPerm)); + ComponentDto project = getProject(module, session); + if (!project.key().equals(module.key())) { + addSettings(ref, module.getKey(), getSettingsFromParents(module, hasScanPerm, session)); + projectKey = project.key(); } + + List moduleChildren = dbClient.componentDao().findChildrenModulesFromModule(session, query.getModuleKey()); + Map moduleUuidsByKey = moduleUuidsByKey(module, moduleChildren); + Map moduleIdsByKey = moduleIdsByKey(module, moduleChildren); + + List moduleChildrenSettings = dbClient.propertiesDao().findChildrenModuleProperties(query.getModuleKey(), session); + TreeModuleSettings treeModuleSettings = new TreeModuleSettings(moduleUuidsByKey, moduleIdsByKey, moduleChildren, moduleChildrenSettings, module); + + addSettingsToChildrenModules(ref, query.getModuleKey(), Maps.newHashMap(), treeModuleSettings, hasScanPerm, session); + addFileData(session, ref, moduleChildren, module.key()); } addProfiles(ref, projectKey, query.getProfileName(), session); addActiveRules(ref); + addManualRules(ref); return ref; } finally { MyBatis.closeQuietly(session); } } - private Map getSettingsFromParents(String moduleKey, boolean hasScanPerm, DbSession session) { + private ComponentDto getProject(ComponentDto module, DbSession session) { + if (!module.isRootProject()) { + return dbClient.componentDao().getNullableByUuid(session, module.projectUuid()); + } else { + return module; + } + } + + private Map getSettingsFromParents(ComponentDto module, boolean hasScanPerm, DbSession session) { List parents = newArrayList(); - aggregateParentModules(moduleKey, parents, session); + aggregateParentModules(module, parents, session); Collections.reverse(parents); Map parentProperties = newHashMap(); @@ -126,11 +134,14 @@ public class ProjectRepositoryLoader implements ServerComponent { return parentProperties; } - private void aggregateParentModules(String component, List parents, DbSession session) { - ComponentDto parent = dbClient.componentDao().getParentModuleByKey(component, session); - if (parent != null) { - parents.add(parent); - aggregateParentModules(parent.key(), parents, session); + private void aggregateParentModules(ComponentDto component, List parents, DbSession session) { + String moduleUuid = component.moduleUuid(); + if (moduleUuid != null) { + ComponentDto parent = dbClient.componentDao().getByUuid(session, moduleUuid); + if (parent != null) { + parents.add(parent); + aggregateParentModules(parent, parents, session); + } } } @@ -220,6 +231,20 @@ public class ProjectRepositoryLoader implements ServerComponent { } } + private void addManualRules(ProjectReferentials ref) { + Result ruleSearchResult = ruleService.search(new RuleQuery().setRepositories(newArrayList(RuleKey.MANUAL_REPOSITORY_KEY)), new QueryContext().setScroll(true) + .setFieldsToReturn(newArrayList(RuleNormalizer.RuleField.KEY.field(), RuleNormalizer.RuleField.NAME.field()))); + Iterator rules = ruleSearchResult.scroll(); + while (rules.hasNext()) { + Rule rule = rules.next(); + ref.addActiveRule(new org.sonar.batch.protocol.input.ActiveRule( + RuleKey.MANUAL_REPOSITORY_KEY, + rule.key().rule(), + rule.name(), + null, null, null)); + } + } + private void addFileData(DbSession session, ProjectReferentials ref, List moduleChildren, String moduleKey) { Map moduleKeysByUuid = newHashMap(); for (ComponentDto module : moduleChildren) { 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 b96b81fdb8b..d91d1d6a71a 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 @@ -83,28 +83,6 @@ public class ComponentDao extends BaseDao return mapper(session).countById(id) > 0; } - /** - * Return null only if the component does not exists. - * If the component if a root project, it will return itself. - */ - @CheckForNull - public ComponentDto getNullableRootProjectByKey(String componentKey, DbSession session) { - return mapper(session).selectRootProjectByKey(componentKey); - } - - public ComponentDto getRootProjectByKey(String componentKey, DbSession session) { - ComponentDto componentDto = getNullableRootProjectByKey(componentKey, session); - if (componentDto == null) { - throw new NotFoundException(String.format("Root project for project '%s' not found", componentKey)); - } - return componentDto; - } - - @CheckForNull - public ComponentDto getParentModuleByKey(String componentKey, DbSession session) { - return mapper(session).selectParentModuleByKey(componentKey); - } - public List findModulesByProject(String projectKey, DbSession session) { return mapper(session).findModulesByProject(projectKey); } 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 a74fcc1b7e1..9790530b312 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 @@ -38,7 +38,6 @@ import org.sonar.api.user.UserFinder; import org.sonar.api.web.UserRole; import org.sonar.core.component.ComponentDto; import org.sonar.core.issue.DefaultIssueBuilder; -import org.sonar.server.issue.notification.IssueNotifications; import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.db.IssueDao; import org.sonar.core.issue.db.IssueDto; @@ -52,6 +51,7 @@ import org.sonar.server.db.DbClient; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.issue.actionplan.ActionPlanService; import org.sonar.server.issue.index.IssueIndex; +import org.sonar.server.issue.notification.IssueNotifications; import org.sonar.server.search.FacetValue; import org.sonar.server.search.IndexClient; import org.sonar.server.search.QueryContext; @@ -251,7 +251,7 @@ public class IssueService implements ServerComponent { DbSession session = dbClient.openSession(false); try { ComponentDto component = dbClient.componentDao().getByKey(session, componentKey); - ComponentDto project = dbClient.componentDao().getRootProjectByKey(componentKey, session); + ComponentDto project = dbClient.componentDao().getByUuid(session, component.projectUuid()); UserSession.get().checkProjectPermission(UserRole.USER, project.getKey()); if (!ruleKey.isManual()) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java index bcc53133743..5726333c222 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java @@ -34,7 +34,6 @@ import org.sonar.batch.protocol.input.FileData; import org.sonar.batch.protocol.input.ProjectReferentials; import org.sonar.batch.protocol.input.QProfile; import org.sonar.core.component.ComponentDto; -import org.sonar.core.component.SnapshotDto; import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.persistence.DbSession; import org.sonar.core.properties.PropertyDto; @@ -44,7 +43,6 @@ import org.sonar.core.rule.RuleParamDto; import org.sonar.core.source.db.FileSourceDao; import org.sonar.core.source.db.FileSourceDto; import org.sonar.server.component.ComponentTesting; -import org.sonar.server.component.SnapshotTesting; import org.sonar.server.db.DbClient; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.qualityprofile.QProfileName; @@ -296,28 +294,6 @@ public class ProjectRepositoryLoaderMediumTest { )); } - @Test - public void return_provisioned_project_settings() throws Exception { - MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); - - // No snapshot attached on the project -> provisioned project - ComponentDto project = ComponentTesting.newProjectDto(); - tester.get(DbClient.class).componentDao().insert(dbSession, project); - addDefaultProfile(); - - // Project properties - tester.get(DbClient.class).propertiesDao().setProperty(new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR").setResourceId(project.getId()), dbSession); - tester.get(DbClient.class).propertiesDao().setProperty(new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(project.getId()), dbSession); - - dbSession.commit(); - - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); - assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of( - "sonar.jira.project.key", "SONAR", - "sonar.jira.login.secured", "john" - )); - } - @Test public void return_sub_module_settings() throws Exception { MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); @@ -357,8 +333,6 @@ public class ProjectRepositoryLoaderMediumTest { ComponentDto project = ComponentTesting.newProjectDto(); tester.get(DbClient.class).componentDao().insert(dbSession, project); - SnapshotDto projectSnapshot = SnapshotTesting.createForProject(project); - tester.get(DbClient.class).snapshotDao().insert(dbSession, projectSnapshot); addDefaultProfile(); // Project property @@ -366,15 +340,12 @@ public class ProjectRepositoryLoaderMediumTest { ComponentDto module = ComponentTesting.newModuleDto(project); tester.get(DbClient.class).componentDao().insert(dbSession, module); - SnapshotDto moduleSnapshot = SnapshotTesting.createForComponent(module, projectSnapshot); - tester.get(DbClient.class).snapshotDao().insert(dbSession, moduleSnapshot); // Module property tester.get(DbClient.class).propertiesDao().setProperty(new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(module.getId()), dbSession); ComponentDto subModule = ComponentTesting.newModuleDto(module); tester.get(DbClient.class).componentDao().insert(dbSession, subModule); - tester.get(DbClient.class).snapshotDao().insert(dbSession, SnapshotTesting.createForComponent(subModule, moduleSnapshot)); // Sub module properties tester.get(DbClient.class).propertiesDao().setProperty(new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(subModule.getId()), dbSession); @@ -397,8 +368,6 @@ public class ProjectRepositoryLoaderMediumTest { ComponentDto project = ComponentTesting.newProjectDto(); tester.get(DbClient.class).componentDao().insert(dbSession, project); - SnapshotDto projectSnapshot = SnapshotTesting.createForProject(project); - tester.get(DbClient.class).snapshotDao().insert(dbSession, projectSnapshot); addDefaultProfile(); // Project properties @@ -408,13 +377,10 @@ public class ProjectRepositoryLoaderMediumTest { ComponentDto module = ComponentTesting.newModuleDto(project); tester.get(DbClient.class).componentDao().insert(dbSession, module); - SnapshotDto moduleSnapshot = SnapshotTesting.createForComponent(module, projectSnapshot); - tester.get(DbClient.class).snapshotDao().insert(dbSession, moduleSnapshot); // No module property ComponentDto subModule = ComponentTesting.newModuleDto(module); tester.get(DbClient.class).componentDao().insert(dbSession, subModule); - tester.get(DbClient.class).snapshotDao().insert(dbSession, SnapshotTesting.createForComponent(subModule, moduleSnapshot)); // No sub module property dbSession.commit(); @@ -435,8 +401,6 @@ public class ProjectRepositoryLoaderMediumTest { ComponentDto project = ComponentTesting.newProjectDto(); tester.get(DbClient.class).componentDao().insert(dbSession, project); - SnapshotDto projectSnapshot = SnapshotTesting.createForProject(project); - tester.get(DbClient.class).snapshotDao().insert(dbSession, projectSnapshot); addDefaultProfile(); // Project properties @@ -445,15 +409,12 @@ public class ProjectRepositoryLoaderMediumTest { ComponentDto module = ComponentTesting.newModuleDto(project); tester.get(DbClient.class).componentDao().insert(dbSession, module); - SnapshotDto moduleSnapshot = SnapshotTesting.createForComponent(module, projectSnapshot); - tester.get(DbClient.class).snapshotDao().insert(dbSession, moduleSnapshot); // Module property tester.get(DbClient.class).propertiesDao().setProperty(new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR-SERVER").setResourceId(module.getId()), dbSession); ComponentDto subModule = ComponentTesting.newModuleDto(module); tester.get(DbClient.class).componentDao().insert(dbSession, subModule); - tester.get(DbClient.class).snapshotDao().insert(dbSession, SnapshotTesting.createForComponent(subModule, moduleSnapshot)); // No sub module property dbSession.commit(); @@ -637,10 +598,31 @@ public class ProjectRepositoryLoaderMediumTest { assertThat(activeRules.get(0).language()).isEqualTo("xoo"); assertThat(activeRules.get(0).severity()).isEqualTo("MINOR"); assertThat(activeRules.get(0).internalKey()).isEqualTo("squid-1"); - assertThat(activeRules.get(0).language()).isEqualTo("xoo"); assertThat(activeRules.get(0).params()).isEqualTo(ImmutableMap.of("max", "2")); } + @Test + public void return_manual_rules() throws Exception { + MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); + + ComponentDto project = ComponentTesting.newProjectDto(); + tester.get(DbClient.class).componentDao().insert(dbSession, project); + addDefaultProfile(); + + RuleDto rule = RuleTesting.newManualRule("manualRuleKey").setName("Name manualRuleKey"); + tester.get(DbClient.class).ruleDao().insert(dbSession, rule); + + dbSession.commit(); + + ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + List activeRules = newArrayList(ref.activeRules()); + assertThat(activeRules).extracting("repositoryKey").containsOnly(RuleKey.MANUAL_REPOSITORY_KEY); + assertThat(activeRules).extracting("ruleKey").containsOnly("manualRuleKey"); + assertThat(activeRules).extracting("name").containsOnly("Name manualRuleKey"); + assertThat(activeRules).extracting("language").containsNull(); + assertThat(activeRules).extracting("severity").containsNull(); + } + @Test public void fail_if_no_permission() throws Exception { MockUserSession.set().setLogin("john").setGlobalPermissions(); 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 aa7a3754861..aaadc8b91fb 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 @@ -256,46 +256,6 @@ public class ComponentDaoTest extends AbstractDaoTestCase { assertThat(dao.findModulesByProject("unknown", session)).isEmpty(); } - @Test - public void get_nullable_root_project_by_key() throws Exception { - setupData("multi-modules"); - - assertThat(dao.getNullableRootProjectByKey("org.struts:struts-data", session).getKey()).isEqualTo("org.struts:struts"); - assertThat(dao.getNullableRootProjectByKey("org.struts:struts-core", session).getKey()).isEqualTo("org.struts:struts"); - - // Root project of a project is itself - assertThat(dao.getNullableRootProjectByKey("org.struts:struts", session).getKey()).isEqualTo("org.struts:struts"); - - assertThat(dao.getNullableRootProjectByKey("unknown", session)).isNull(); - } - - @Test - public void get_root_project_by_key() throws Exception { - setupData("multi-modules"); - - assertThat(dao.getRootProjectByKey("org.struts:struts-data", session).getKey()).isEqualTo("org.struts:struts"); - assertThat(dao.getRootProjectByKey("org.struts:struts-core", session).getKey()).isEqualTo("org.struts:struts"); - - // Root project of a project is itself - assertThat(dao.getRootProjectByKey("org.struts:struts", session).getKey()).isEqualTo("org.struts:struts"); - } - - @Test(expected = NotFoundException.class) - public void get_root_project_by_key_on_unknown_project() throws Exception { - dao.getRootProjectByKey("unknown", session); - } - - @Test - public void get_parent_module_by_key() throws Exception { - setupData("multi-modules"); - - assertThat(dao.getParentModuleByKey("org.struts:struts-data", session).getKey()).isEqualTo("org.struts:struts-core"); - assertThat(dao.getParentModuleByKey("org.struts:struts-core", session).getKey()).isEqualTo("org.struts:struts"); - assertThat(dao.getParentModuleByKey("org.struts:struts", session)).isNull(); - - assertThat(dao.getParentModuleByKey("unknown", session)).isNull(); - } - @Test public void find_sub_projects_by_component_keys() throws Exception { setupData("multi-modules"); diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java index 6cfd273bce4..0cba9544e0b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RuleTesting.java @@ -98,7 +98,7 @@ public class RuleTesting { public static RuleDto newManualRule(String manualKey){ return new RuleDto().setRuleKey(manualKey) .setName("Name " + manualKey) - .setRepositoryKey("manual") + .setRepositoryKey(RuleKey.MANUAL_REPOSITORY_KEY) .setDescription("Description " + manualKey) .setStatus(RuleStatus.READY); } 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 2c6cfe91be4..04e4335382a 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 @@ -52,12 +52,6 @@ public interface ComponentMapper { @CheckForNull ComponentDto selectByUuid(String uuid); - @CheckForNull - ComponentDto selectRootProjectByKey(String key); - - @CheckForNull - ComponentDto selectParentModuleByKey(String key); - /** * Return direct modules from a project/module */ 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 b47c06374d6..d8067bf1215 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 @@ -62,27 +62,6 @@ - - - -