From: Julien Lancelot Date: Fri, 26 Aug 2016 15:18:45 +0000 (+0200) Subject: SONAR-7986 Remove property set values when removing property set X-Git-Tag: 6.1-RC1~272 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=98330dc19f1f972ff0bf6e88fb827d9e6141a12f;p=sonarqube.git SONAR-7986 Remove property set values when removing property set --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/settings/ws/PropertySetExtractor.java b/server/sonar-server/src/main/java/org/sonar/server/settings/ws/PropertySetExtractor.java new file mode 100644 index 00000000000..2e27c1da45b --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/settings/ws/PropertySetExtractor.java @@ -0,0 +1,48 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.settings.ws; + +import com.google.common.base.Splitter; +import java.util.HashSet; +import java.util.Set; +import org.sonar.api.config.PropertyDefinition; +import org.sonar.db.property.PropertyDto; + +public class PropertySetExtractor { + + private static final Splitter COMMA_SPLITTER = Splitter.on(","); + + private PropertySetExtractor() { + // Only static stuff + } + + public static Set extractPropertySetKeys(PropertyDto propertyDto, PropertyDefinition definition) { + Set propertySetKeys = new HashSet<>(); + definition.fields() + .forEach(field -> COMMA_SPLITTER.splitToList(propertyDto.getValue()) + .forEach(setId -> propertySetKeys.add(generatePropertySetKey(propertyDto.getKey(), setId, field.key())))); + return propertySetKeys; + } + + private static String generatePropertySetKey(String propertyBaseKey, String id, String fieldKey) { + return propertyBaseKey + "." + id + "." + fieldKey; + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/settings/ws/ResetAction.java b/server/sonar-server/src/main/java/org/sonar/server/settings/ws/ResetAction.java index 6442e6c27bd..3c24e053d7b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/settings/ws/ResetAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/settings/ws/ResetAction.java @@ -44,12 +44,14 @@ import static org.sonarqube.ws.client.setting.SettingsWsParameters.PARAM_KEY; public class ResetAction implements SettingsWsAction { private final DbClient dbClient; - private final UserSession userSession; private final ComponentFinder componentFinder; + private final SettingsUpdater settingsUpdater; + private final UserSession userSession; private final PropertyDefinitions definitions; - public ResetAction(DbClient dbClient, ComponentFinder componentFinder, UserSession userSession, PropertyDefinitions definitions) { + public ResetAction(DbClient dbClient, ComponentFinder componentFinder, SettingsUpdater settingsUpdater, UserSession userSession, PropertyDefinitions definitions) { this.dbClient = dbClient; + this.settingsUpdater = settingsUpdater; this.userSession = userSession; this.componentFinder = componentFinder; this.definitions = definitions; @@ -87,9 +89,9 @@ public class ResetAction implements SettingsWsAction { PropertyDefinition definition = definitions.get(resetRequest.getKey()); String key = definition != null ? definition.key() : resetRequest.getKey(); if (component.isPresent()) { - dbClient.propertiesDao().deleteProjectProperty(key, component.get().getId(), dbSession); + settingsUpdater.deleteComponentSetting(dbSession, key, component.get()); } else { - dbClient.propertiesDao().deleteGlobalProperty(key, dbSession); + settingsUpdater.deleteGlobalSetting(dbSession, key); } dbSession.commit(); response.noContent(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/settings/ws/SettingsFinder.java b/server/sonar-server/src/main/java/org/sonar/server/settings/ws/SettingsFinder.java index e2ed8ffd35d..11c5011310f 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/settings/ws/SettingsFinder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/settings/ws/SettingsFinder.java @@ -24,7 +24,6 @@ import com.google.common.base.Splitter; import com.google.common.collect.Multimap; import com.google.common.collect.Ordering; import com.google.common.collect.TreeMultimap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -38,11 +37,11 @@ import org.sonar.db.component.ComponentDto; import org.sonar.db.property.PropertyDto; import static org.sonar.api.PropertyType.PROPERTY_SET; +import static org.sonar.server.settings.ws.PropertySetExtractor.extractPropertySetKeys; public class SettingsFinder { private static final Splitter DOT_SPLITTER = Splitter.on(".").omitEmptyStrings(); - private static final Splitter COMMA_SPLITTER = Splitter.on(","); private final DbClient dbClient; private final PropertyDefinitions definitions; @@ -83,18 +82,11 @@ public class SettingsFinder { } private Set getPropertySetKeys(List properties) { - Set propertySetKeys = new HashSet<>(); - properties.stream() + return properties.stream() .filter(propertyDto -> definitions.get(propertyDto.getKey()) != null) .filter(propertyDto -> definitions.get(propertyDto.getKey()).type().equals(PROPERTY_SET)) - .forEach(propertyDto -> definitions.get(propertyDto.getKey()).fields() - .forEach(field -> COMMA_SPLITTER.splitToList(propertyDto.getValue()) - .forEach(setId -> propertySetKeys.add(generatePropertySetKey(propertyDto.getKey(), setId, field.key()))))); - return propertySetKeys; - } - - private static String generatePropertySetKey(String propertyBaseKey, String id, String fieldKey) { - return propertyBaseKey + "." + id + "." + fieldKey; + .flatMap(propertyDto -> extractPropertySetKeys(propertyDto, definitions.get(propertyDto.getKey())).stream()) + .collect(Collectors.toSet()); } private static List getPropertySets(String propertyKey, List propertySets, @Nullable Long componentId) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/settings/ws/SettingsUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/settings/ws/SettingsUpdater.java new file mode 100644 index 00000000000..270913f362b --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/settings/ws/SettingsUpdater.java @@ -0,0 +1,91 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.settings.ws; + +import java.util.Optional; +import java.util.Set; +import org.sonar.api.PropertyType; +import org.sonar.api.config.PropertyDefinition; +import org.sonar.api.config.PropertyDefinitions; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.property.PropertyDto; + +import static org.sonar.server.settings.ws.PropertySetExtractor.extractPropertySetKeys; + +public class SettingsUpdater { + + private final DbClient dbClient; + private final PropertyDefinitions definitions; + + public SettingsUpdater(DbClient dbClient, PropertyDefinitions definitions) { + this.dbClient = dbClient; + this.definitions = definitions; + } + + public void deleteGlobalSetting(DbSession dbSession, String propertyKey) { + delete(dbSession, propertyKey, Optional.empty()); + } + + public void deleteComponentSetting(DbSession dbSession, String propertyKey, ComponentDto componentDto) { + delete(dbSession, propertyKey, Optional.of(componentDto)); + } + + private void delete(DbSession dbSession, String propertyKey, Optional componentDto) { + PropertyDefinition definition = definitions.get(propertyKey); + if (definition == null || !definition.type().equals(PropertyType.PROPERTY_SET)) { + deleteSetting(dbSession, propertyKey, componentDto); + } else { + deletePropertySet(dbSession, propertyKey, definition, componentDto); + } + } + + private void deleteSetting(DbSession dbSession, String propertyKey, Optional componentDto) { + if (componentDto.isPresent()) { + dbClient.propertiesDao().deleteProjectProperty(propertyKey, componentDto.get().getId(), dbSession); + } else { + dbClient.propertiesDao().deleteGlobalProperty(propertyKey, dbSession); + } + } + + private void deletePropertySet(DbSession dbSession, String propertyKey, PropertyDefinition definition, Optional componentDto) { + Optional propertyDto = selectPropertyDto(dbSession, propertyKey, componentDto); + if (!propertyDto.isPresent()) { + // Setting doesn't exist, nothing to do + return; + } + Set propertySetKeys = extractPropertySetKeys(propertyDto.get(), definition); + for (String key : propertySetKeys) { + deleteSetting(dbSession, key, componentDto); + } + deleteSetting(dbSession, propertyKey, componentDto); + } + + private Optional selectPropertyDto(DbSession dbSession, String propertyKey, Optional componentDto) { + if (componentDto.isPresent()) { + return Optional.ofNullable(dbClient.propertiesDao().selectProjectProperty(dbSession, componentDto.get().getId(), propertyKey)); + } else { + return Optional.ofNullable(dbClient.propertiesDao().selectGlobalProperty(dbSession, propertyKey)); + } + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/settings/ws/SettingsWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/settings/ws/SettingsWsModule.java index 9624d697e5b..5a1caa02652 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/settings/ws/SettingsWsModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/settings/ws/SettingsWsModule.java @@ -31,6 +31,7 @@ public class SettingsWsModule extends Module { ListDefinitionsAction.class, ValuesAction.class, SettingsFinder.class, - ResetAction.class); + ResetAction.class, + SettingsUpdater.class); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/settings/ws/ResetActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/settings/ws/ResetActionTest.java index 0b37723dd94..1663cee0eaf 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/settings/ws/ResetActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/settings/ws/ResetActionTest.java @@ -39,6 +39,7 @@ import org.sonar.db.property.PropertyQuery; import org.sonar.db.user.UserDto; import org.sonar.db.user.UserTesting; import org.sonar.server.component.ComponentFinder; +import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.TestRequest; import org.sonar.server.ws.TestResponse; @@ -48,6 +49,8 @@ import org.sonarqube.ws.MediaTypes; import static java.net.HttpURLConnection.HTTP_NO_CONTENT; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.api.web.UserRole.ADMIN; +import static org.sonar.api.web.UserRole.USER; +import static org.sonar.core.permission.GlobalPermissions.DASHBOARD_SHARING; import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; import static org.sonar.db.component.ComponentTesting.newProjectDto; import static org.sonar.db.property.PropertyTesting.newComponentPropertyDto; @@ -71,10 +74,11 @@ public class ResetActionTest { DbSession dbSession = db.getSession(); ComponentFinder componentFinder = new ComponentFinder(dbClient); PropertyDefinitions definitions = new PropertyDefinitions(); + SettingsUpdater settingsUpdater = new SettingsUpdater(dbClient, definitions); ComponentDto project; - ResetAction underTest = new ResetAction(dbClient, componentFinder, userSession, definitions); + ResetAction underTest = new ResetAction(dbClient, componentFinder, settingsUpdater, userSession, definitions); WsActionTester ws = new WsActionTester(underTest); @Before @@ -93,7 +97,7 @@ public class ResetActionTest { @Test public void remove_component_setting() throws Exception { - setUserAsSystemAdmin(); + setUserAsProjectAdmin(); propertyDb.insertProperties(newComponentPropertyDto(project).setKey("foo").setValue("value")); executeRequestOnProjectSetting("foo"); @@ -114,7 +118,7 @@ public class ResetActionTest { @Test public void ignore_global_setting_when_removing_project_setting() throws Exception { - setUserAsSystemAdmin(); + setUserAsProjectAdmin(); propertyDb.insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one")); propertyDb.insertProperties(newComponentPropertyDto(project).setKey("foo").setValue("value")); @@ -136,7 +140,7 @@ public class ResetActionTest { @Test public void ignore_user_setting_when_removing_project_setting() throws Exception { - setUserAsSystemAdmin(); + setUserAsProjectAdmin(); UserDto user = dbClient.userDao().insert(dbSession, UserTesting.newUserDto()); propertyDb.insertProperties(newUserPropertyDto("foo", "one", user)); @@ -182,6 +186,26 @@ public class ResetActionTest { assertThat(action.params()).hasSize(3); } + @Test + public void fail_when_not_system_admin() throws Exception { + userSession.login("not-admin").setGlobalPermissions(DASHBOARD_SHARING); + definitions.addComponent(PropertyDefinition.builder("foo").build()); + + expectedException.expect(ForbiddenException.class); + + executeRequestOnGlobalSetting("foo"); + } + + @Test + public void fail_when_not_project_admin() throws Exception { + userSession.login("project-admin").addProjectUuidPermissions(USER, project.uuid()); + definitions.addComponent(PropertyDefinition.builder("foo").build()); + + expectedException.expect(ForbiddenException.class); + + executeRequestOnComponentSetting("foo", project); + } + private void executeRequestOnGlobalSetting(String key) { executeRequest(key, null, null); } @@ -216,11 +240,11 @@ public class ResetActionTest { } private void assertGlobalPropertyDoesNotExist(String key) { - assertThat(dbClient.propertiesDao().selectGlobalProperty(key)).isNull(); + assertThat(dbClient.propertiesDao().selectGlobalProperty(dbSession, key)).isNull(); } private void assertGlobalPropertyExists(String key) { - assertThat(dbClient.propertiesDao().selectGlobalProperty(key)).isNotNull(); + assertThat(dbClient.propertiesDao().selectGlobalProperty(dbSession, key)).isNotNull(); } private void assertProjectPropertyDoesNotExist(String key) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/settings/ws/SettingsUpdaterTest.java b/server/sonar-server/src/test/java/org/sonar/server/settings/ws/SettingsUpdaterTest.java new file mode 100644 index 00000000000..7ac5c0f4e9b --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/settings/ws/SettingsUpdaterTest.java @@ -0,0 +1,200 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.settings.ws; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.PropertyType; +import org.sonar.api.config.PropertyDefinition; +import org.sonar.api.config.PropertyDefinitions; +import org.sonar.api.config.PropertyFieldDefinition; +import org.sonar.api.utils.System2; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDbTester; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.property.PropertyDbTester; +import org.sonar.db.property.PropertyQuery; +import org.sonar.db.user.UserDto; +import org.sonar.db.user.UserTesting; + +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.db.component.ComponentTesting.newProjectDto; +import static org.sonar.db.property.PropertyTesting.newComponentPropertyDto; +import static org.sonar.db.property.PropertyTesting.newGlobalPropertyDto; +import static org.sonar.db.property.PropertyTesting.newUserPropertyDto; + +public class SettingsUpdaterTest { + + @Rule + public DbTester db = DbTester.create(System2.INSTANCE); + + DbClient dbClient = db.getDbClient(); + DbSession dbSession = db.getSession(); + + PropertyDbTester propertyDb = new PropertyDbTester(db); + ComponentDbTester componentDb = new ComponentDbTester(db); + + PropertyDefinitions definitions = new PropertyDefinitions(); + ComponentDto project; + + SettingsUpdater underTest= new SettingsUpdater(dbClient, definitions); + + @Before + public void setUp() throws Exception { + project = componentDb.insertComponent(newProjectDto()); + } + + @Test + public void delete_global_setting() throws Exception { + definitions.addComponent(PropertyDefinition.builder("foo").build()); + propertyDb.insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one")); + propertyDb.insertProperties(newComponentPropertyDto(project).setKey("foo").setValue("value")); + + underTest.deleteGlobalSetting(dbSession, "foo"); + + assertGlobalPropertyDoesNotExist("foo"); + assertProjectPropertyExists("foo"); + } + + @Test + public void delete_component_setting() throws Exception { + definitions.addComponent(PropertyDefinition.builder("foo").build()); + propertyDb.insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one")); + propertyDb.insertProperties(newComponentPropertyDto(project).setKey("foo").setValue("value")); + + underTest.deleteComponentSetting(dbSession, "foo", project); + + assertProjectPropertyDoesNotExist("foo"); + assertGlobalPropertyExists("foo"); + } + + @Test + public void does_not_fail_when_deleting_unknown_setting() throws Exception { + propertyDb.insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one")); + + underTest.deleteGlobalSetting(dbSession, "unknown"); + + assertGlobalPropertyExists("foo"); + } + + @Test + public void does_not_delete_user_settings() throws Exception { + UserDto user = dbClient.userDao().insert(dbSession, UserTesting.newUserDto()); + propertyDb.insertProperties(newUserPropertyDto("foo", "one", user)); + propertyDb.insertProperties(newGlobalPropertyDto().setKey("foo").setValue("one")); + + underTest.deleteGlobalSetting(dbSession, "foo"); + + assertUserPropertyExists("foo", user); + } + + @Test + public void delete_global_property_set() throws Exception { + definitions.addComponent(PropertyDefinition + .builder("foo") + .type(PropertyType.PROPERTY_SET) + .fields(asList( + PropertyFieldDefinition.build("key").name("Key").build(), + PropertyFieldDefinition.build("size").name("Size").build())) + .build()); + propertyDb.insertProperties( + newGlobalPropertyDto().setKey("foo").setValue("1,2"), + newGlobalPropertyDto().setKey("foo.1.key").setValue("key1"), + newGlobalPropertyDto().setKey("foo.1.size").setValue("size1"), + newGlobalPropertyDto().setKey("foo.2.key").setValue("key2")); + + underTest.deleteGlobalSetting(dbSession, "foo"); + + assertGlobalPropertyDoesNotExist("foo"); + assertGlobalPropertyDoesNotExist("foo.1.key"); + assertGlobalPropertyDoesNotExist("foo.1.size"); + assertGlobalPropertyDoesNotExist("foo.2.key"); + } + + @Test + public void delete_component_property_set() throws Exception { + definitions.addComponent(PropertyDefinition + .builder("foo") + .type(PropertyType.PROPERTY_SET) + .fields(asList( + PropertyFieldDefinition.build("key").name("Key").build(), + PropertyFieldDefinition.build("size").name("Size").build())) + .build()); + propertyDb.insertProperties( + newComponentPropertyDto(project).setKey("foo").setValue("1,2"), + newComponentPropertyDto(project).setKey("foo.1.key").setValue("key1"), + newComponentPropertyDto(project).setKey("foo.1.size").setValue("size1"), + newComponentPropertyDto(project).setKey("foo.2.key").setValue("key2")); + + underTest.deleteComponentSetting(dbSession, "foo", project); + + assertProjectPropertyDoesNotExist("foo"); + assertProjectPropertyDoesNotExist("foo.1.key"); + assertProjectPropertyDoesNotExist("foo.1.size"); + assertProjectPropertyDoesNotExist("foo.2.key"); + } + + @Test + public void does_not_fail_when_deleting_unknown_property_set() throws Exception { + definitions.addComponent(PropertyDefinition + .builder("foo") + .type(PropertyType.PROPERTY_SET) + .fields(asList( + PropertyFieldDefinition.build("key").name("Key").build(), + PropertyFieldDefinition.build("size").name("Size").build())) + .build()); + propertyDb.insertProperties( + newComponentPropertyDto(project).setKey("other").setValue("1,2"), + newComponentPropertyDto(project).setKey("other.1.key").setValue("key1")); + + underTest.deleteComponentSetting(dbSession, "foo", project); + + assertProjectPropertyExists("other"); + } + + private void assertGlobalPropertyDoesNotExist(String key) { + assertThat(dbClient.propertiesDao().selectGlobalProperty(dbSession, key)).isNull(); + } + + private void assertGlobalPropertyExists(String key) { + assertThat(dbClient.propertiesDao().selectGlobalProperty(dbSession, key)).isNotNull(); + } + + private void assertProjectPropertyDoesNotExist(String key) { + assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentId(project.getId()).setKey(key).build(), dbSession)).isEmpty(); + } + + private void assertProjectPropertyExists(String key) { + assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder().setComponentId(project.getId()).setKey(key).build(), dbSession)).isNotEmpty(); + } + + private void assertUserPropertyExists(String key, UserDto user) { + assertThat(dbClient.propertiesDao().selectByQuery(PropertyQuery.builder() + .setKey(key) + .setUserId(user.getId().intValue()) + .build(), + dbSession)).isNotEmpty(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/settings/ws/SettingsWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/settings/ws/SettingsWsModuleTest.java index f476c5db1b1..18a54cfd494 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/settings/ws/SettingsWsModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/settings/ws/SettingsWsModuleTest.java @@ -29,6 +29,6 @@ public class SettingsWsModuleTest { public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new SettingsWsModule().configure(container); - assertThat(container.size()).isEqualTo(7 + 2); + assertThat(container.size()).isEqualTo(8 + 2); } } diff --git a/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java b/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java index 38683018c91..cba42d90e9f 100644 --- a/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java +++ b/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java @@ -152,14 +152,18 @@ public class PropertiesDao implements Dao { @CheckForNull public PropertyDto selectProjectProperty(long resourceId, String propertyKey) { DbSession session = mybatis.openSession(false); - PropertiesMapper mapper = session.getMapper(PropertiesMapper.class); try { - return mapper.selectByKey(new PropertyDto().setKey(propertyKey).setResourceId(resourceId)); + return selectProjectProperty(session, resourceId, propertyKey); } finally { MyBatis.closeQuietly(session); } } + @CheckForNull + public PropertyDto selectProjectProperty(DbSession dbSession, long resourceId, String propertyKey) { + return dbSession.getMapper(PropertiesMapper.class).selectByKey(new PropertyDto().setKey(propertyKey).setResourceId(resourceId)); + } + public List selectByQuery(PropertyQuery query, DbSession session) { return session.getMapper(PropertiesMapper.class).selectByQuery(query); }