From ef9869ca12457efb552c7abd4517c334ed839c66 Mon Sep 17 00:00:00 2001 From: Julien Lancelot Date: Thu, 24 Jul 2014 09:21:51 +0200 Subject: [PATCH] SONAR-5417 Return quality profiles and settings by module --- .../java/org/sonar/server/batch/BatchWs.java | 5 +- .../batch/GlobalReferentialsAction.java | 2 +- .../batch/ProjectReferentialsAction.java | 137 ++++++++++++++++ .../component/persistence/ComponentDao.java | 18 +- .../server/platform/ServerComponents.java | 2 + .../qualityprofile/QProfileFactory.java | 15 +- .../QProfileProjectOperations.java | 12 +- .../server/qualityprofile/QProfiles.java | 6 +- .../org/sonar/server/batch/BatchWsTest.java | 6 +- .../batch/GlobalReferentialsActionTest.java | 2 +- .../batch/ProjectReferentialsActionTest.java | 154 ++++++++++++++++++ .../persistence/ComponentDaoTest.java | 12 ++ .../QProfileFactoryMediumTest.java | 28 ++++ ..._quality_profile_from_default_profile.json | 13 ++ .../return_quality_profiles.json | 13 ++ .../return_settings_by_modules.json | 14 ++ ...modules_without_empty_module_settings.json | 11 ++ .../core/component/db/ComponentMapper.java | 5 + .../sonar/core/properties/PropertiesDao.java | 7 +- .../qualityprofile/db/QualityProfileDao.java | 7 +- .../db/QualityProfileMapper.java | 4 +- .../core/component/db/ComponentMapper.xml | 30 +++- .../db/QualityProfileMapper.xml | 14 +- .../db/QualityProfileDaoTest.java | 21 ++- 24 files changed, 509 insertions(+), 29 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/batch/ProjectReferentialsAction.java create mode 100644 server/sonar-server/src/test/java/org/sonar/server/batch/ProjectReferentialsActionTest.java create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_quality_profile_from_default_profile.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_quality_profiles.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_settings_by_modules.json create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_settings_by_modules_without_empty_module_settings.json diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/BatchWs.java b/server/sonar-server/src/main/java/org/sonar/server/batch/BatchWs.java index 948ae241714..39f5fc8c695 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/BatchWs.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/BatchWs.java @@ -32,10 +32,12 @@ public class BatchWs implements WebService { private final BatchIndex batchIndex; private final GlobalReferentialsAction globalReferentialsAction; + private final ProjectReferentialsAction projectReferentialsAction; - public BatchWs(BatchIndex batchIndex, GlobalReferentialsAction globalReferentialsAction) { + public BatchWs(BatchIndex batchIndex, GlobalReferentialsAction globalReferentialsAction, ProjectReferentialsAction projectReferentialsAction) { this.batchIndex = batchIndex; this.globalReferentialsAction = globalReferentialsAction; + this.projectReferentialsAction = projectReferentialsAction; } @Override @@ -47,6 +49,7 @@ public class BatchWs implements WebService { defineIndexAction(controller); defineFileAction(controller); globalReferentialsAction.define(controller); + projectReferentialsAction.define(controller); controller.done(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalReferentialsAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalReferentialsAction.java index 286f37021be..03251c89695 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalReferentialsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/GlobalReferentialsAction.java @@ -101,7 +101,7 @@ public class GlobalReferentialsAction implements RequestHandler { } } - private boolean isPropertyAllowed(String key, boolean hasScanPerm, boolean hasDryRunPerm){ + private static boolean isPropertyAllowed(String key, boolean hasScanPerm, boolean hasDryRunPerm) { return !key.contains(".secured") || hasScanPerm || (key.contains(".license") && hasDryRunPerm); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectReferentialsAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectReferentialsAction.java new file mode 100644 index 00000000000..8b4a9f23054 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectReferentialsAction.java @@ -0,0 +1,137 @@ +/* + * 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.batch; + +import org.apache.commons.io.IOUtils; +import org.sonar.api.resources.Language; +import org.sonar.api.resources.Languages; +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.RequestHandler; +import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService; +import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.QProfile; +import org.sonar.core.UtcDateUtils; +import org.sonar.core.component.ComponentDto; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; +import org.sonar.core.properties.PropertiesDao; +import org.sonar.core.properties.PropertyDto; +import org.sonar.core.qualityprofile.db.QualityProfileDto; +import org.sonar.server.db.DbClient; +import org.sonar.server.plugins.MimeTypes; +import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.user.UserSession; + +import java.util.List; +import java.util.Map; + +import static com.google.common.collect.Maps.newHashMap; + +public class ProjectReferentialsAction implements RequestHandler { + + private static final String PARAM_KEY = "key"; + + private final DbClient dbClient; + private final PropertiesDao propertiesDao; + private final QProfileFactory qProfileFactory; + private final Languages languages; + + public ProjectReferentialsAction(DbClient dbClient, PropertiesDao propertiesDao, QProfileFactory qProfileFactory, Languages languages) { + this.dbClient = dbClient; + this.propertiesDao = propertiesDao; + this.qProfileFactory = qProfileFactory; + this.languages = languages; + } + + void define(WebService.NewController controller) { + WebService.NewAction action = controller.createAction("project") + .setDescription("Return project referentials") + .setSince("4.5") + .setInternal(true) + .setHandler(this); + + action + .createParam(PARAM_KEY) + .setRequired(true) + .setDescription("Project key") + .setExampleValue("org.codehaus.sonar:sonar"); + } + + @Override + public void handle(Request request, Response response) throws Exception { + UserSession userSession = UserSession.get(); + boolean hasScanPerm = userSession.hasGlobalPermission(GlobalPermissions.SCAN_EXECUTION); + + DbSession session = dbClient.openSession(false); + try { + ProjectReferentials ref = new ProjectReferentials(); + String projectKey = request.mandatoryParam(PARAM_KEY); + addSettings(ref, projectKey, hasScanPerm, session); + addProfiles(ref, projectKey, session); + + response.stream().setMediaType(MimeTypes.JSON); + IOUtils.write(ref.toJson(), response.stream().output()); + } finally { + MyBatis.closeQuietly(session); + } + } + + private void addSettings(ProjectReferentials ref, String projectKey, boolean hasScanPerm, DbSession session) { + addSettings(ref, projectKey, propertiesDao.selectProjectProperties(projectKey, session), hasScanPerm); + for (ComponentDto module : dbClient.componentDao().findModulesByProject(projectKey, session)) { + addSettings(ref, module.getKey(), propertiesDao.selectProjectProperties(module.getKey(), session), hasScanPerm); + } + } + + private void addSettings(ProjectReferentials ref, String projectOrModuleKey, List propertyDtos, boolean hasScanPerm) { + Map properties = newHashMap(); + for (PropertyDto propertyDto : propertyDtos) { + String key = propertyDto.getKey(); + String value = propertyDto.getValue(); + if (isPropertyAllowed(key, hasScanPerm)) { + properties.put(key, value); + } + } + if (!properties.isEmpty()) { + ref.addSettings(projectOrModuleKey, properties); + } + } + + private static boolean isPropertyAllowed(String key, boolean hasScanPerm) { + return !key.contains(".secured") || hasScanPerm; + } + + private void addProfiles(ProjectReferentials ref, String projectKey, DbSession session) { + for (Language language : languages.all()) { + String languageKey = language.getKey(); + QualityProfileDto qualityProfileDto = qProfileFactory.getByProjectAndLanguage(session, projectKey, languageKey); + qualityProfileDto = qualityProfileDto != null ? qualityProfileDto : qProfileFactory.getDefault(session, languageKey); + if (qualityProfileDto != null) { + QProfile profile = new QProfile(qualityProfileDto.getKey(), qualityProfileDto.getName(), qualityProfileDto.getLanguage(), + UtcDateUtils.parseDateTime(qualityProfileDto.getRulesUpdatedAt())); + ref.addQProfile(profile); + } + } + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/persistence/ComponentDao.java b/server/sonar-server/src/main/java/org/sonar/server/component/persistence/ComponentDao.java index 940bd4d344e..39a23370fdf 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/persistence/ComponentDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/persistence/ComponentDao.java @@ -19,7 +19,6 @@ */ package org.sonar.server.component.persistence; -import org.apache.ibatis.session.SqlSession; import org.sonar.api.ServerComponent; import org.sonar.api.utils.System2; import org.sonar.core.component.ComponentDto; @@ -29,6 +28,7 @@ import org.sonar.core.persistence.DbSession; import org.sonar.server.db.BaseDao; import java.util.Date; +import java.util.List; /** * @since 4.3 @@ -39,26 +39,26 @@ public class ComponentDao extends BaseDao super(ComponentMapper.class, system); } - public ComponentDto getById(Long id, SqlSession session) { - return getMapper(session).selectById(id); + public ComponentDto getById(Long id, DbSession session) { + return mapper(session).selectById(id); } - public boolean existsById(Long id, SqlSession session) { - return getMapper(session).countById(id) > 0; + public boolean existsById(Long id, DbSession session) { + return mapper(session).countById(id) > 0; } - private ComponentMapper getMapper(SqlSession session) { - return session.getMapper(ComponentMapper.class); + public List findModulesByProject(String projectKey, DbSession session) { + return mapper(session).findModulesByProject(projectKey); } @Override protected ComponentDto doGetNullableByKey(DbSession session, String key) { - return getMapper(session).selectByKey(key); + return mapper(session).selectByKey(key); } @Override protected ComponentDto doInsert(DbSession session, ComponentDto item) { - getMapper(session).insert(item); + mapper(session).insert(item); return item; } 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 db2109db7f9..91023ef5a0e 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 @@ -81,6 +81,7 @@ import org.sonar.server.authentication.ws.AuthenticationWs; import org.sonar.server.batch.BatchIndex; import org.sonar.server.batch.BatchWs; import org.sonar.server.batch.GlobalReferentialsAction; +import org.sonar.server.batch.ProjectReferentialsAction; import org.sonar.server.charts.ChartFactory; import org.sonar.server.component.DefaultComponentFinder; import org.sonar.server.component.DefaultRubyComponentService; @@ -296,6 +297,7 @@ class ServerComponents { // batch pico.addSingleton(BatchIndex.class); pico.addSingleton(GlobalReferentialsAction.class); + pico.addSingleton(ProjectReferentialsAction.class); pico.addSingleton(BatchWs.class); // update center diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java index a6fa81675e6..0e7b1042e12 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileFactory.java @@ -141,7 +141,7 @@ public class QProfileFactory implements ServerComponent { } @CheckForNull - QualityProfileDto getDefault(DbSession session, String language) { + public QualityProfileDto getDefault(DbSession session, String language) { return db.qualityProfileDao().getDefaultProfile(language, session); } @@ -168,6 +168,19 @@ public class QProfileFactory implements ServerComponent { db.propertiesDao().setProperty(property, session); } + QualityProfileDto getByProjectAndLanguage(String projectKey, String language) { + DbSession dbSession = db.openSession(false); + try { + return getByProjectAndLanguage(dbSession, projectKey, language); + } finally { + dbSession.close(); + } + } + + public QualityProfileDto getByProjectAndLanguage(DbSession session, String projectKey, String language) { + return db.qualityProfileDao().getByProjectAndLanguage(projectKey, language, PROFILE_PROPERTY_PREFIX + language, session); + } + private void checkNotDefault(@Nullable QualityProfileDto defaultProfile, QualityProfileDto p) { if (defaultProfile != null && defaultProfile.getKey().equals(p.getKey())) { throw new BadRequestException("The profile marked as default can not be deleted: " + p.getKey()); diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java index f1e694297ca..da24181f9fb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfileProjectOperations.java @@ -44,15 +44,21 @@ public class QProfileProjectOperations implements ServerComponent { checkPermission(userSession); DbSession session = db.openSession(false); try { + addProject(profileId, projectId, userSession, session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } + } + + void addProject(int profileId, long projectId, UserSession userSession, DbSession session) { + checkPermission(userSession); ComponentDto project = (ComponentDto) findProjectNotNull(projectId, session); QualityProfileDto qualityProfile = findNotNull(profileId, session); db.propertiesDao().setProperty(new PropertyDto().setKey( QProfileProjectLookup.PROFILE_PROPERTY_PREFIX + qualityProfile.getLanguage()).setValue(qualityProfile.getName()).setResourceId(project.getId()), session); session.commit(); - } finally { - MyBatis.closeQuietly(session); - } } public void removeProject(int profileId, long projectId, UserSession userSession) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java index e36b55dae05..b3559277ad1 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/QProfiles.java @@ -31,6 +31,10 @@ import javax.annotation.CheckForNull; import java.util.List; +/** + * Use {@link org.sonar.server.qualityprofile.QProfileService} instead + */ +@Deprecated public class QProfiles implements ServerComponent { private static final String LANGUAGE_PARAM = "language"; @@ -90,7 +94,7 @@ public class QProfiles implements ServerComponent { } /** - * Used in /project/profile + * Used in /project/profile and in /api/profiles */ @CheckForNull public QProfile findProfileByProjectAndLanguage(long projectId, String language) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsTest.java index bef1af04f54..50a7c340705 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/BatchWsTest.java @@ -28,8 +28,10 @@ import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.resources.Languages; import org.sonar.core.properties.PropertiesDao; import org.sonar.server.db.DbClient; +import org.sonar.server.qualityprofile.QProfileFactory; import org.sonar.server.ws.WsTester; import java.io.File; @@ -55,7 +57,9 @@ public class BatchWsTest { @Before public void before() throws IOException { - tester = new WsTester(new BatchWs(batchIndex, new GlobalReferentialsAction(mock(DbClient.class), mock(PropertiesDao.class)))); + tester = new WsTester(new BatchWs(batchIndex, + new GlobalReferentialsAction(mock(DbClient.class), mock(PropertiesDao.class)), + new ProjectReferentialsAction(mock(DbClient.class), mock(PropertiesDao.class), mock(QProfileFactory.class), mock(Languages.class)))); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalReferentialsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalReferentialsActionTest.java index d3f9fb9906a..4468e1b7f66 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalReferentialsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/GlobalReferentialsActionTest.java @@ -59,7 +59,7 @@ public class GlobalReferentialsActionTest { when(dbClient.openSession(false)).thenReturn(session); when(dbClient.metricDao()).thenReturn(metricDao); - tester = new WsTester(new BatchWs(mock(BatchIndex.class), new GlobalReferentialsAction(dbClient, propertiesDao))); + tester = new WsTester(new BatchWs(mock(BatchIndex.class), new GlobalReferentialsAction(dbClient, propertiesDao), mock(ProjectReferentialsAction.class))); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectReferentialsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectReferentialsActionTest.java new file mode 100644 index 00000000000..a04fcc58cf6 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectReferentialsActionTest.java @@ -0,0 +1,154 @@ +/* + * 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.batch; + +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.resources.Language; +import org.sonar.api.resources.Languages; +import org.sonar.core.component.ComponentDto; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.properties.PropertiesDao; +import org.sonar.core.properties.PropertyDto; +import org.sonar.core.qualityprofile.db.QualityProfileDto; +import org.sonar.server.component.persistence.ComponentDao; +import org.sonar.server.db.DbClient; +import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.user.MockUserSession; +import org.sonar.server.ws.WsTester; + +import static com.google.common.collect.Lists.newArrayList; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class ProjectReferentialsActionTest { + + @Mock + DbSession session; + + @Mock + ComponentDao componentDao; + + @Mock + PropertiesDao propertiesDao; + + @Mock + QProfileFactory qProfileFactory; + + @Mock + Languages languages; + + @Mock + Language language; + + WsTester tester; + + @Before + public void setUp() throws Exception { + DbClient dbClient = mock(DbClient.class); + when(dbClient.openSession(false)).thenReturn(session); + when(dbClient.componentDao()).thenReturn(componentDao); + + when(language.getKey()).thenReturn("java"); + when(languages.all()).thenReturn(new Language[]{language}); + + tester = new WsTester(new BatchWs(mock(BatchIndex.class), mock(GlobalReferentialsAction.class), new ProjectReferentialsAction(dbClient, propertiesDao, qProfileFactory, languages))); + } + + @Test + public void return_settings_by_modules() throws Exception { + MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.DRY_RUN_EXECUTION); + String projectKey = "org.codehaus.sonar:sonar"; + String moduleKey = "org.codehaus.sonar:sonar-server"; + + when(componentDao.findModulesByProject(projectKey, session)).thenReturn(newArrayList( + new ComponentDto().setKey(projectKey), + new ComponentDto().setKey(moduleKey) + )); + + when(propertiesDao.selectProjectProperties(projectKey, session)).thenReturn(newArrayList( + new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR"), + new PropertyDto().setKey("sonar.jira.login.secured").setValue("john") + )); + + when(propertiesDao.selectProjectProperties(moduleKey, session)).thenReturn(newArrayList( + new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java") + )); + + WsTester.TestRequest request = tester.newGetRequest("batch", "project").setParam("key", projectKey); + request.execute().assertJson(getClass(), "return_settings_by_modules.json"); + } + + @Test + public void return_settings_by_modules_without_empty_module_settings() throws Exception { + MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.DRY_RUN_EXECUTION); + String projectKey = "org.codehaus.sonar:sonar"; + String moduleKey = "org.codehaus.sonar:sonar-server"; + + when(componentDao.findModulesByProject(projectKey, session)).thenReturn(newArrayList( + new ComponentDto().setKey(projectKey), + new ComponentDto().setKey(moduleKey) + )); + + when(propertiesDao.selectProjectProperties(projectKey, session)).thenReturn(newArrayList( + new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR"), + new PropertyDto().setKey("sonar.jira.login.secured").setValue("john") + )); + // No property on module + + WsTester.TestRequest request = tester.newGetRequest("batch", "project").setParam("key", projectKey); + request.execute().assertJson(getClass(), "return_settings_by_modules_without_empty_module_settings.json"); + } + + @Test + public void return_quality_profiles() throws Exception { + MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.DRY_RUN_EXECUTION); + + String projectKey = "org.codehaus.sonar:sonar"; + + when(qProfileFactory.getByProjectAndLanguage(session, projectKey, "java")).thenReturn( + QualityProfileDto.createFor("abcd").setName("Default").setLanguage("java").setRulesUpdatedAt("2014-01-14T14:00:00+0200") + ); + + WsTester.TestRequest request = tester.newGetRequest("batch", "project").setParam("key", projectKey); + request.execute().assertJson(getClass(), "return_quality_profiles.json"); + } + + @Test + public void return_quality_profile_from_default_profile() throws Exception { + MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION, GlobalPermissions.DRY_RUN_EXECUTION); + + String projectKey = "org.codehaus.sonar:sonar"; + + when(qProfileFactory.getDefault(session, "java")).thenReturn( + QualityProfileDto.createFor("abcd").setName("Default").setLanguage("java").setRulesUpdatedAt("2014-01-14T14:00:00+0200") + ); + + WsTester.TestRequest request = tester.newGetRequest("batch", "project").setParam("key", projectKey); + request.execute().assertJson(getClass(), "return_quality_profile_from_default_profile.json"); + } + +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/persistence/ComponentDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/persistence/ComponentDaoTest.java index 4d794a8c9ad..c5cb63a11b5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/persistence/ComponentDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/persistence/ComponentDaoTest.java @@ -29,6 +29,7 @@ import org.sonar.core.persistence.AbstractDaoTestCase; import org.sonar.core.persistence.DbSession; import java.util.Date; +import java.util.List; import static org.fest.assertions.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -106,6 +107,17 @@ public class ComponentDaoTest extends AbstractDaoTestCase { assertThat(dao.existsById(111L, session)).isFalse(); } + @Test + public void find_modules_by_project() throws Exception { + setupData("shared"); + + List results = dao.findModulesByProject("org.struts:struts", session); + assertThat(results).hasSize(1); + assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts-core"); + + assertThat(dao.findModulesByProject("unknown", session)).isEmpty(); + } + @Test public void insert() { when(system2.now()).thenReturn(DateUtils.parseDate("2014-06-18").getTime()); diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryMediumTest.java index caaab96473b..cfcb07c5eae 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/QProfileFactoryMediumTest.java @@ -24,6 +24,8 @@ import org.junit.Before; import org.junit.ClassRule; import org.junit.Test; import org.sonar.api.server.rule.RuleParamType; +import org.sonar.core.component.ComponentDto; +import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.persistence.DbSession; import org.sonar.core.properties.PropertyDto; import org.sonar.core.qualityprofile.db.QualityProfileDto; @@ -35,6 +37,7 @@ import org.sonar.server.qualityprofile.index.ActiveRuleIndex; import org.sonar.server.rule.RuleTesting; import org.sonar.server.search.IndexClient; import org.sonar.server.tester.ServerTester; +import org.sonar.server.user.MockUserSession; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; @@ -300,6 +303,31 @@ public class QProfileFactoryMediumTest { } } + @Test + public void get_profile_by_project_and_language() { + ComponentDto project = new ComponentDto() + .setId(1L) + .setKey("org.codehaus.sonar:sonar") + .setName("SonarQube") + .setLongName("SonarQube") + .setQualifier("TRK") + .setScope("TRK") + .setEnabled(true); + db.componentDao().insert(dbSession, project); + + QualityProfileDto profileDto = QProfileTesting.newXooP1(); + db.qualityProfileDao().insert(dbSession, profileDto); + dbSession.commit(); + dbSession.clearCache(); + assertThat(factory.getByProjectAndLanguage("org.codehaus.sonar:sonar", "xoo")).isNull(); + + tester.get(QProfileProjectOperations.class).addProject(profileDto.getId(), project.getId(), + MockUserSession.set().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN), dbSession); + dbSession.commit(); + dbSession.clearCache(); + assertThat(factory.getByProjectAndLanguage("org.codehaus.sonar:sonar", "xoo").getKey()).isEqualTo(XOO_P1_KEY); + } + private void initRules() { // create pre-defined rules RuleDto xooRule1 = RuleTesting.newXooX1(); diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_quality_profile_from_default_profile.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_quality_profile_from_default_profile.json new file mode 100644 index 00000000000..a1bb33bb01f --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_quality_profile_from_default_profile.json @@ -0,0 +1,13 @@ +{ + "timestamp": 0, + "qprofilesByLanguage": { + "java": { + "key": "abcd", + "name": "Default", + "language": "java", + "rulesUpdatedAt": "Jan 14, 2014 1:00:00 PM" + } + }, + "activeRules": [], + "settingsByModule": {} +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_quality_profiles.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_quality_profiles.json new file mode 100644 index 00000000000..a1bb33bb01f --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_quality_profiles.json @@ -0,0 +1,13 @@ +{ + "timestamp": 0, + "qprofilesByLanguage": { + "java": { + "key": "abcd", + "name": "Default", + "language": "java", + "rulesUpdatedAt": "Jan 14, 2014 1:00:00 PM" + } + }, + "activeRules": [], + "settingsByModule": {} +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_settings_by_modules.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_settings_by_modules.json new file mode 100644 index 00000000000..8891c4589eb --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_settings_by_modules.json @@ -0,0 +1,14 @@ +{ + "timestamp": 0, + "qprofilesByLanguage": {}, + "activeRules": [], + "settingsByModule": { + "org.codehaus.sonar:sonar": { + "sonar.jira.project.key": "SONAR", + "sonar.jira.login.secured": "john" + }, + "org.codehaus.sonar:sonar-server": { + "sonar.coverage.exclusions": "**/*.java" + } + } +} diff --git a/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_settings_by_modules_without_empty_module_settings.json b/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_settings_by_modules_without_empty_module_settings.json new file mode 100644 index 00000000000..5ca420c2a6d --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/batch/ProjectReferentialsActionTest/return_settings_by_modules_without_empty_module_settings.json @@ -0,0 +1,11 @@ +{ + "timestamp": 0, + "qprofilesByLanguage": {}, + "activeRules": [], + "settingsByModule": { + "org.codehaus.sonar:sonar": { + "sonar.jira.project.key": "SONAR", + "sonar.jira.login.secured": "john" + } + } +} 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 cb8c8dac1a0..9d74af46428 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 @@ -19,8 +19,11 @@ */ package org.sonar.core.component.db; +import org.apache.ibatis.annotations.Param; import org.sonar.core.component.ComponentDto; +import java.util.List; + /** * @since 4.3 */ @@ -30,6 +33,8 @@ public interface ComponentMapper { ComponentDto selectById(long id); + List findModulesByProject(@Param("projectKey") String projectKey); + long countById(long id); void insert(ComponentDto rule); diff --git a/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java b/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java index 756ed70d824..4357258a1b4 100644 --- a/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java +++ b/sonar-core/src/main/java/org/sonar/core/properties/PropertiesDao.java @@ -95,11 +95,14 @@ public class PropertiesDao implements BatchComponent, ServerComponent, DaoCompon } } + public List selectProjectProperties(String resourceKey, SqlSession session) { + return session.getMapper(PropertiesMapper.class).selectProjectProperties(resourceKey); + } + public List selectProjectProperties(String resourceKey) { SqlSession session = mybatis.openSession(false); - PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); try { - return mapper.selectProjectProperties(resourceKey); + return selectProjectProperties(resourceKey, session); } finally { MyBatis.closeQuietly(session); } diff --git a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java index 45189d64df9..01244ef1ae2 100644 --- a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java +++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java @@ -187,12 +187,17 @@ public class QualityProfileDao implements ServerComponent, DaoComponent { public QualityProfileDto getByProjectAndLanguage(long projectId, String language, String key) { DbSession session = mybatis.openSession(false); try { - return session.getMapper(QualityProfileMapper.class).selectByProjectAndLanguage(projectId, language, key); + return session.getMapper(QualityProfileMapper.class).selectByProjectIdAndLanguage(projectId, language, key); } finally { MyBatis.closeQuietly(session); } } + @CheckForNull + public QualityProfileDto getByProjectAndLanguage(String projectKey, String language, String propertyKeyPrefix, DbSession session) { + return session.getMapper(QualityProfileMapper.class).selectByProjectAndLanguage(projectKey, language, propertyKeyPrefix); + } + public List findByLanguage(String language) { DbSession session = mybatis.openSession(false); try { diff --git a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java index cef07f9a24a..3ba36880451 100644 --- a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java @@ -67,5 +67,7 @@ public interface QualityProfileMapper { int countProjects(@Param("value") String propertyValue, @Param("key") String propertyKey); - QualityProfileDto selectByProjectAndLanguage(@Param("projectId") Long projectId, @Param("language") String language, @Param("key") String propertyKeyPrefix); + QualityProfileDto selectByProjectIdAndLanguage(@Param("projectId") Long projectId, @Param("language") String language, @Param("key") String propertyKeyPrefix); + + QualityProfileDto selectByProjectAndLanguage(@Param("projectKey") String projectKey, @Param("language") String language, @Param("propertyKey") String propertyKeyPrefix); } 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 de9ad8a46b5..f0dc353a03a 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 @@ -18,21 +18,41 @@ + + diff --git a/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml b/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml index 84c2ae5e101..b8a6ea50889 100644 --- a/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml @@ -114,7 +114,7 @@ - SELECT FROM rules_profiles p INNER JOIN properties prop ON prop.resource_id=#{projectId} @@ -123,5 +123,17 @@ WHERE p.language=#{language} + + diff --git a/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java b/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java index 1f1c8554acf..21386e7be70 100644 --- a/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java +++ b/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java @@ -20,6 +20,7 @@ package org.sonar.core.qualityprofile.db; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.sonar.api.utils.System2; @@ -36,14 +37,21 @@ import static org.mockito.Mockito.when; public class QualityProfileDaoTest extends AbstractDaoTestCase { QualityProfileDao dao; + DbSession session; System2 system = mock(System2.class); @Before public void createDao() { + this.session = getMyBatis().openSession(false); dao = new QualityProfileDao(getMyBatis(), system); when(system.now()).thenReturn(UtcDateUtils.parseDateTime("2014-01-20T12:00:00+0000").getTime()); } + @After + public void after() { + this.session.close(); + } + @Test public void insert() { setupData("shared"); @@ -217,10 +225,21 @@ public class QualityProfileDaoTest extends AbstractDaoTestCase { } @Test - public void select_by_project_and_language() { + public void select_by_project_id_and_language() { setupData("projects"); QualityProfileDto dto = dao.getByProjectAndLanguage(1L, "java", "sonar.profile.java"); assertThat(dto.getId()).isEqualTo(1); } + + @Test + public void select_by_project_key_and_language() { + setupData("projects"); + + QualityProfileDto dto = dao.getByProjectAndLanguage("org.codehaus.sonar:sonar", "java", "sonar.profile.java", session); + assertThat(dto.getId()).isEqualTo(1); + + assertThat(dao.getByProjectAndLanguage("org.codehaus.sonar:sonar", "unkown", "sonar.profile.java", session)).isNull(); + assertThat(dao.getByProjectAndLanguage("unknown", "java", "sonar.profile.java", session)).isNull(); + } } -- 2.39.5