diff options
22 files changed, 556 insertions, 152 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentTreeQuery.java b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentTreeQuery.java index 6119f3cb9ae..a6099250007 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentTreeQuery.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/component/ComponentTreeQuery.java @@ -42,12 +42,15 @@ public class ComponentTreeQuery { // SONAR-7681 a public implementation of List must be used in MyBatis - potential concurrency exceptions otherwise @CheckForNull private final ArrayList<String> qualifiers; + @CheckForNull + private final ArrayList<String> scopes; private final String baseUuid; private final Strategy strategy; private ComponentTreeQuery(Builder builder) { this.nameOrKeyQuery = builder.nameOrKeyQuery; this.qualifiers = builder.qualifiers == null ? null : newArrayList(builder.qualifiers); + this.scopes = builder.scopes == null ? null : newArrayList(builder.scopes); this.baseUuid = builder.baseUuid; this.strategy = requireNonNull(builder.strategy); } @@ -58,6 +61,11 @@ public class ComponentTreeQuery { } @CheckForNull + public Collection<String> getScopes() { + return scopes; + } + + @CheckForNull public String getNameOrKeyQuery() { return nameOrKeyQuery; } @@ -98,6 +106,8 @@ public class ComponentTreeQuery { private String nameOrKeyQuery; @CheckForNull private Collection<String> qualifiers; + @CheckForNull + private Collection<String> scopes; private String baseUuid; private Strategy strategy; @@ -120,6 +130,11 @@ public class ComponentTreeQuery { return this; } + public Builder setScopes(Collection<String> scopes) { + this.scopes = scopes; + return this; + } + public Builder setBaseUuid(String uuid) { this.baseUuid = uuid; return this; diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeConfiguration.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeConfiguration.java index 245c23c7c6a..219d1afcfa7 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeConfiguration.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeConfiguration.java @@ -20,6 +20,7 @@ package org.sonar.db.purge; import com.google.common.annotations.VisibleForTesting; +import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.Optional; @@ -30,16 +31,18 @@ import org.sonar.api.resources.Scopes; import org.sonar.api.utils.System2; import org.sonar.core.config.PurgeConstants; +import static java.util.Collections.singletonList; + public class PurgeConfiguration { private final IdUuidPair rootProjectIdUuid; - private final String[] scopesWithoutHistoricalData; + private final Collection<String> scopesWithoutHistoricalData; private final int maxAgeInDaysOfClosedIssues; private final Optional<Integer> maxAgeInDaysOfInactiveShortLivingBranches; private final System2 system2; private final Collection<String> disabledComponentUuids; - public PurgeConfiguration(IdUuidPair rootProjectId, String[] scopesWithoutHistoricalData, int maxAgeInDaysOfClosedIssues, + public PurgeConfiguration(IdUuidPair rootProjectId, Collection<String> scopesWithoutHistoricalData, int maxAgeInDaysOfClosedIssues, Optional<Integer> maxAgeInDaysOfInactiveShortLivingBranches, System2 system2, Collection<String> disabledComponentUuids) { this.rootProjectIdUuid = rootProjectId; this.scopesWithoutHistoricalData = scopesWithoutHistoricalData; @@ -50,9 +53,9 @@ public class PurgeConfiguration { } public static PurgeConfiguration newDefaultPurgeConfiguration(Configuration config, IdUuidPair rootId, Collection<String> disabledComponentUuids) { - String[] scopes = new String[] {Scopes.FILE}; + Collection<String> scopes = singletonList(Scopes.FILE); if (config.getBoolean(PurgeConstants.PROPERTY_CLEAN_DIRECTORY).orElse(false)) { - scopes = new String[] {Scopes.DIRECTORY, Scopes.FILE}; + scopes = Arrays.asList(Scopes.DIRECTORY, Scopes.FILE); } return new PurgeConfiguration(rootId, scopes, config.getInt(PurgeConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES).get(), config.getInt(PurgeConstants.DAYS_BEFORE_DELETING_INACTIVE_SHORT_LIVING_BRANCHES), System2.INSTANCE, disabledComponentUuids); @@ -62,7 +65,7 @@ public class PurgeConfiguration { return rootProjectIdUuid; } - public String[] scopesWithoutHistoricalData() { + public Collection<String> getScopesWithoutHistoricalData() { return scopesWithoutHistoricalData; } diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java index cad8376dc39..81909236663 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/purge/PurgeDao.java @@ -21,7 +21,6 @@ package org.sonar.db.purge; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; @@ -64,7 +63,7 @@ public class PurgeDao implements Dao { PurgeCommands commands = new PurgeCommands(session, mapper, profiler); String rootUuid = conf.rootProjectIdUuid().getUuid(); deleteAbortedAnalyses(rootUuid, commands); - deleteDataOfComponentsWithoutHistoricalData(session, rootUuid, conf.scopesWithoutHistoricalData(), commands); + deleteDataOfComponentsWithoutHistoricalData(session, rootUuid, conf.getScopesWithoutHistoricalData(), commands); purgeAnalyses(commands, rootUuid); purgeDisabledComponents(session, conf, listener); deleteOldClosedIssues(conf, mapper, listener); @@ -119,8 +118,8 @@ public class PurgeDao implements Dao { commands.deleteAnalyses(query); } - private void deleteDataOfComponentsWithoutHistoricalData(DbSession dbSession, String rootUuid, String[] scopesWithoutHistoricalData, PurgeCommands purgeCommands) { - if (scopesWithoutHistoricalData.length == 0) { + private void deleteDataOfComponentsWithoutHistoricalData(DbSession dbSession, String rootUuid, Collection<String> scopesWithoutHistoricalData, PurgeCommands purgeCommands) { + if (scopesWithoutHistoricalData.isEmpty()) { return; } @@ -134,7 +133,7 @@ public class PurgeDao implements Dao { dbSession, ComponentTreeQuery.builder() .setBaseUuid(rootUuid) - .setQualifiers(Arrays.asList(scopesWithoutHistoricalData)) + .setScopes(scopesWithoutHistoricalData) .setStrategy(Strategy.LEAVES) .build()) .stream().map(ComponentDto::uuid) diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml index 22991a65e29..e415632ecf7 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/component/ComponentMapper.xml @@ -373,6 +373,12 @@ #{qualifier,jdbcType=VARCHAR} </foreach> </if> + <if test="query.scopes != null"> + and p.scope in + <foreach collection="query.scopes" item="scope" open="(" close=")" separator=","> + #{scope,jdbcType=VARCHAR} + </foreach> + </if> <if test="query.nameOrKeyQuery != null"> and ( p.kee = #{query.nameOrKeyQuery,jdbcType=VARCHAR} diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml index 57eb8f87008..0c9db60b475 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/LiveMeasureMapper.xml @@ -92,7 +92,20 @@ lm.metric_id in <foreach item="metricId" collection="query.getMetricIds()" open="(" separator="," close=")">#{metricId,jdbcType=INTEGER}</foreach> </if> - <include refid="org.sonar.db.component.ComponentMapper.selectDescendantsFilters"/> + and p.enabled = ${_true} + <if test="query.qualifiers != null"> + and p.qualifier in + <foreach collection="query.qualifiers" item="qualifier" open="(" close=")" separator=","> + #{qualifier,jdbcType=VARCHAR} + </foreach> + </if> + <if test="query.nameOrKeyQuery != null"> + and ( + p.kee = #{query.nameOrKeyQuery,jdbcType=VARCHAR} + or + upper(p.name) like #{query.nameOrKeyUpperLikeQuery,jdbcType=VARCHAR} escape '/' + ) + </if> </where> -- Add measures of base component @@ -104,7 +117,20 @@ lm.metric_id in <foreach item="metricId" collection="query.getMetricIds()" open="(" separator="," close=")">#{metricId,jdbcType=INTEGER}</foreach> </if> - <include refid="org.sonar.db.component.ComponentMapper.selectDescendantsFilters"/> + and p.enabled = ${_true} + <if test="query.qualifiers != null"> + and p.qualifier in + <foreach collection="query.qualifiers" item="qualifier" open="(" close=")" separator=","> + #{qualifier,jdbcType=VARCHAR} + </foreach> + </if> + <if test="query.nameOrKeyQuery != null"> + and ( + p.kee = #{query.nameOrKeyQuery,jdbcType=VARCHAR} + or + upper(p.name) like #{query.nameOrKeyUpperLikeQuery,jdbcType=VARCHAR} escape '/' + ) + </if> </where> </select> </mapper> diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml index 4dd4ecd7504..a5d4d313c7b 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/measure/MeasureMapper.xml @@ -21,9 +21,9 @@ inner join metrics m on m.id = pm.metric_id inner join snapshots s on s.uuid = pm.analysis_uuid where - pm.component_uuid = #{componentUuid,jdbcType=VARCHAR} and - m.name = #{metricKey,jdbcType=VARCHAR} and - s.islast= ${_true} + pm.component_uuid = #{componentUuid,jdbcType=VARCHAR} and + m.name = #{metricKey,jdbcType=VARCHAR} and + s.islast= ${_true} </select> <select id="selectMeasure" parameterType="map" resultType="Measure"> @@ -65,7 +65,7 @@ select <include refid="measureColumns"/> from project_measures pm <include refid="selectByQueryCommonJoins"/> inner join projects p on p.project_uuid=analysis.component_uuid - and p.uuid=pm.component_uuid + and p.uuid=pm.component_uuid where <include refid="selectByQueryCommonFilters"/> and pm.component_uuid=#{query.componentUuid,jdbcType=VARCHAR} @@ -102,15 +102,15 @@ from project_measures pm inner join snapshots analysis on analysis.uuid = pm.analysis_uuid where - pm.component_uuid = #{componentUuid,jdbcType=VARCHAR} - and analysis.uuid = #{analysisUuid,jdbcType=VARCHAR} - and pm.metric_id in <foreach item="metricId" collection="metricIds" open="(" separator="," close=")">#{metricId}</foreach> + pm.component_uuid = #{componentUuid,jdbcType=VARCHAR} + and analysis.uuid = #{analysisUuid,jdbcType=VARCHAR} + and pm.metric_id in <foreach item="metricId" collection="metricIds" open="(" separator="," close=")">#{metricId}</foreach> </select> <select id="selectPastMeasuresOnSeveralAnalyses" parameterType="map" resultType="Measure"> select <include refid="measureColumns"/> from project_measures pm - inner join snapshots analysis on analysis.uuid = pm.analysis_uuid + inner join snapshots analysis on analysis.uuid = pm.analysis_uuid where pm.component_uuid = #{query.componentUuid, jdbcType=VARCHAR} <if test="query.from!= null"> diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java index 7ffbbb8371e..a8448836c7e 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/component/ComponentDaoTest.java @@ -34,6 +34,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.resources.Qualifiers; +import org.sonar.api.resources.Scopes; import org.sonar.api.utils.System2; import org.sonar.db.DbSession; import org.sonar.db.DbTester; @@ -1280,18 +1281,18 @@ public class ComponentDaoTest { } @Test - public void select_descendants_with_children_stragegy() { + public void select_descendants_with_children_strategy() { // project has 2 children: module and file 1. Other files are part of module. ComponentDto project = newPrivateProjectDto(db.organizations().insert(), PROJECT_UUID); db.components().insertProjectAndSnapshot(project); ComponentDto module = newModuleDto(MODULE_UUID, project); db.components().insertComponent(module); - ComponentDto file1 = newFileDto(project, null, FILE_1_UUID).setDbKey("file-key-1").setName("File One"); - db.components().insertComponent(file1); - ComponentDto file2 = newFileDto(module, null, FILE_2_UUID).setDbKey("file-key-2").setName("File Two"); - db.components().insertComponent(file2); - ComponentDto file3 = newFileDto(module, null, FILE_3_UUID).setDbKey("file-key-3").setName("File Three"); - db.components().insertComponent(file3); + ComponentDto fileInProject = newFileDto(project, null, FILE_1_UUID).setDbKey("file-key-1").setName("File One"); + db.components().insertComponent(fileInProject); + ComponentDto file1InModule = newFileDto(module, null, FILE_2_UUID).setDbKey("file-key-2").setName("File Two"); + db.components().insertComponent(file1InModule); + ComponentDto file2InModule = newFileDto(module, null, FILE_3_UUID).setDbKey("file-key-3").setName("File Three"); + db.components().insertComponent(file2InModule); db.commit(); // test children of root @@ -1343,6 +1344,16 @@ public class ComponentDaoTest { // test children of leaf component (file here), matching name query = newTreeQuery(FILE_1_UUID).setNameOrKeyQuery("Foo").build(); assertThat(underTest.selectDescendants(dbSession, query)).isEmpty(); + + // test filtering by scope + query = newTreeQuery(project.uuid()).setScopes(asList(Scopes.FILE)).build(); + assertThat(underTest.selectDescendants(dbSession, query)) + .extracting(ComponentDto::uuid) + .containsExactlyInAnyOrder(fileInProject.uuid()); + query = newTreeQuery(project.uuid()).setScopes(asList(Scopes.PROJECT)).build(); + assertThat(underTest.selectDescendants(dbSession, query)) + .extracting(ComponentDto::uuid) + .containsExactlyInAnyOrder(module.uuid()); } @Test diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeConfigurationTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeConfigurationTest.java index a55713eb734..1e0dc38b671 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeConfigurationTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeConfigurationTest.java @@ -19,7 +19,6 @@ */ package org.sonar.db.purge; -import java.util.Collections; import java.util.Date; import java.util.Optional; import org.junit.Test; @@ -31,15 +30,16 @@ import org.sonar.api.utils.System2; import org.sonar.core.config.PurgeConstants; import org.sonar.core.config.PurgeProperties; +import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; public class PurgeConfigurationTest { @Test public void should_delete_all_closed_issues() { - PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 0, Optional.empty(), System2.INSTANCE, Collections.emptyList()); + PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), emptyList(), 0, Optional.empty(), System2.INSTANCE, emptyList()); assertThat(conf.maxLiveDateOfClosedIssues()).isNull(); - conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], -1, Optional.empty(), System2.INSTANCE, Collections.emptyList()); + conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), emptyList(), -1, Optional.empty(), System2.INSTANCE, emptyList()); assertThat(conf.maxLiveDateOfClosedIssues()).isNull(); } @@ -47,7 +47,7 @@ public class PurgeConfigurationTest { public void should_delete_only_old_closed_issues() { Date now = DateUtils.parseDate("2013-05-18"); - PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 30, Optional.empty(), System2.INSTANCE, Collections.emptyList()); + PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), emptyList(), 30, Optional.empty(), System2.INSTANCE, emptyList()); Date toDate = conf.maxLiveDateOfClosedIssues(now); assertThat(toDate.getYear()).isEqualTo(113);// =2013 @@ -57,7 +57,7 @@ public class PurgeConfigurationTest { @Test public void should_have_empty_branch_purge_date() { - PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 30, Optional.of(10), System2.INSTANCE, Collections.emptyList()); + PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), emptyList(), 30, Optional.of(10), System2.INSTANCE, emptyList()); assertThat(conf.maxLiveDateOfInactiveShortLivingBranches()).isNotEmpty(); long tenDaysAgo = DateUtils.addDays(new Date(System2.INSTANCE.now()), -10).getTime(); assertThat(conf.maxLiveDateOfInactiveShortLivingBranches().get().getTime()).isBetween(tenDaysAgo - 5000, tenDaysAgo + 5000); @@ -65,31 +65,32 @@ public class PurgeConfigurationTest { @Test public void should_calculate_branch_purge_date() { - PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 30, Optional.empty(), System2.INSTANCE, Collections.emptyList()); + PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(1L, "1"), emptyList(), 30, Optional.empty(), System2.INSTANCE, emptyList()); assertThat(conf.maxLiveDateOfInactiveShortLivingBranches()).isEmpty(); } @Test - public void do_not_delete_directory_by_default() { + public void delete_files_but_not_directories_by_default() { MapSettings settings = new MapSettings(new PropertyDefinitions(PurgeProperties.all())); settings.setProperty(PurgeConstants.PROPERTY_CLEAN_DIRECTORY, false); settings.setProperty(PurgeConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES, 5); Date now = new Date(); - PurgeConfiguration underTest = PurgeConfiguration.newDefaultPurgeConfiguration(settings.asConfig(), new IdUuidPair(42L, "any-uuid"), Collections.emptyList()); + PurgeConfiguration underTest = PurgeConfiguration.newDefaultPurgeConfiguration(settings.asConfig(), new IdUuidPair(42L, "any-uuid"), emptyList()); - assertThat(underTest.scopesWithoutHistoricalData()).contains(Scopes.FILE) - .doesNotContain(Scopes.DIRECTORY); + assertThat(underTest.getScopesWithoutHistoricalData()) + .containsExactlyInAnyOrder(Scopes.FILE); assertThat(underTest.maxLiveDateOfClosedIssues(now)).isEqualTo(DateUtils.addDays(now, -5)); } @Test - public void delete_directory_if_in_settings() { + public void delete_directory_if_enabled_in_settings() { MapSettings settings = new MapSettings(new PropertyDefinitions(PurgeProperties.all())); settings.setProperty(PurgeConstants.PROPERTY_CLEAN_DIRECTORY, true); - PurgeConfiguration underTest = PurgeConfiguration.newDefaultPurgeConfiguration(settings.asConfig(), new IdUuidPair(42L, "any-uuid"), Collections.emptyList()); + PurgeConfiguration underTest = PurgeConfiguration.newDefaultPurgeConfiguration(settings.asConfig(), new IdUuidPair(42L, "any-uuid"), emptyList()); - assertThat(underTest.scopesWithoutHistoricalData()).contains(Scopes.DIRECTORY, Scopes.FILE); + assertThat(underTest.getScopesWithoutHistoricalData()) + .containsExactlyInAnyOrder(Scopes.DIRECTORY, Scopes.FILE); } } diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java index f618a131fa4..880ff481004 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/purge/PurgeDaoTest.java @@ -55,6 +55,7 @@ import org.sonar.db.property.PropertyDto; import org.sonar.db.rule.RuleDefinitionDto; import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static org.assertj.core.api.Assertions.assertThat; @@ -133,13 +134,13 @@ public class PurgeDaoTest { @Test public void shouldDeleteHistoricalDataOfDirectoriesAndFiles() { dbTester.prepareDbUnit(getClass(), "shouldDeleteHistoricalDataOfDirectoriesAndFiles.xml"); - PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(THE_PROJECT_ID, "ABCD"), new String[] {Scopes.DIRECTORY, Scopes.FILE}, + PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(THE_PROJECT_ID, "PROJECT_UUID"), asList(Scopes.DIRECTORY, Scopes.FILE), 30, Optional.of(30), System2.INSTANCE, Collections.emptyList()); underTest.purge(dbSession, conf, PurgeListener.EMPTY, new PurgeProfiler()); dbSession.commit(); - dbTester.assertDbUnit(getClass(), "shouldDeleteHistoricalDataOfDirectoriesAndFiles-result.xml", "projects", "snapshots"); + dbTester.assertDbUnit(getClass(), "shouldDeleteHistoricalDataOfDirectoriesAndFiles-result.xml", "projects", "snapshots", "project_measures"); } @Test @@ -358,7 +359,7 @@ public class PurgeDaoTest { @Test public void should_delete_all_closed_issues() { dbTester.prepareDbUnit(getClass(), "should_delete_all_closed_issues.xml"); - PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(THE_PROJECT_ID, "1"), new String[0], + PurgeConfiguration conf = new PurgeConfiguration(new IdUuidPair(THE_PROJECT_ID, "1"), emptyList(), 0, Optional.empty(), System2.INSTANCE, Collections.emptyList()); underTest.purge(dbSession, conf, PurgeListener.EMPTY, new PurgeProfiler()); dbSession.commit(); @@ -648,11 +649,11 @@ public class PurgeDaoTest { } private static PurgeConfiguration newConfigurationWith30Days() { - return new PurgeConfiguration(new IdUuidPair(THE_PROJECT_ID, THE_PROJECT_UUID), new String[0], 30, Optional.of(30), System2.INSTANCE, Collections.emptyList()); + return new PurgeConfiguration(new IdUuidPair(THE_PROJECT_ID, THE_PROJECT_UUID), emptyList(), 30, Optional.of(30), System2.INSTANCE, Collections.emptyList()); } private static PurgeConfiguration newConfigurationWith30Days(System2 system2, String rootProjectUuid, String... disabledComponentUuids) { - return new PurgeConfiguration(new IdUuidPair(THE_PROJECT_ID, rootProjectUuid), new String[0], 30, Optional.of(30), system2, asList(disabledComponentUuids)); + return new PurgeConfiguration(new IdUuidPair(THE_PROJECT_ID, rootProjectUuid), emptyList(), 30, Optional.of(30), system2, asList(disabledComponentUuids)); } } diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles-result.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles-result.xml index 3e6532b606a..e84a82ff99e 100644 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles-result.xml +++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles-result.xml @@ -1,16 +1,10 @@ -<!-- - -What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 (DIR/FIL) are deleted - ---> - <dataset> <!-- the project --> <projects organization_uuid="org1" - uuid="ABCD" + uuid="PROJECT_UUID" uuid_path="." - project_uuid="ABCD" + project_uuid="PROJECT_UUID" module_uuid="[null]" module_uuid_path="." main_branch_project_uuid="[null]" @@ -22,7 +16,6 @@ What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 name="project" description="[null]" private="[false]" - tags="[null]" language="java" copy_component_uuid="[null]" developer_uuid="[null]" @@ -31,7 +24,8 @@ What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 authorization_updated_at="[null]" id="1" enabled="[true]" - root_uuid="ABCD" + root_uuid="PROJECT_UUID" + tags="[null]" b_changed="[false]" b_copy_component_uuid="[null]" b_description="[null]" @@ -48,10 +42,10 @@ What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 <!-- the directory --> <projects organization_uuid="org1" - uuid="EFGH" - uuid_path=".ABCD." - project_uuid="ABCD" - module_uuid="ABCD" + uuid="DIR_UUID" + uuid_path=".PROJECT_UUID." + project_uuid="PROJECT_UUID" + module_uuid="PROJECT_UUID" module_uuid_path="." main_branch_project_uuid="[null]" created_at="[null]" @@ -62,7 +56,6 @@ What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 name="my/dir" description="[null]" private="[false]" - tags="[null]" language="java" copy_component_uuid="[null]" developer_uuid="[null]" @@ -71,7 +64,8 @@ What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 authorization_updated_at="[null]" id="2" enabled="[true]" - root_uuid="ABCD" + root_uuid="PROJECT_UUID" + tags="[null]" b_changed="[false]" b_copy_component_uuid="[null]" b_description="[null]" @@ -88,11 +82,11 @@ What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 <!-- the file --> <projects organization_uuid="org1" - uuid="GHIJ" - uuid_path=".ABCD.EFGH." - project_uuid="ABCD" - module_uuid="ABCD" - module_uuid_path=".ABCD." + uuid="FILE_UUID" + uuid_path=".PROJECT_UUID.DIR_UUID." + project_uuid="PROJECT_UUID" + module_uuid="PROJECT_UUID" + module_uuid_path=".PROJECT_UUID." main_branch_project_uuid="[null]" created_at="[null]" long_name="[null]" @@ -102,7 +96,6 @@ What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 name="my/dir/File.java" description="[null]" private="[false]" - tags="[null]" language="java" copy_component_uuid="[null]" developer_uuid="[null]" @@ -111,7 +104,48 @@ What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 authorization_updated_at="[null]" id="3" enabled="[true]" - root_uuid="ABCD" + root_uuid="PROJECT_UUID" + tags="[null]" + b_changed="[false]" + b_copy_component_uuid="[null]" + b_description="[null]" + b_enabled="[false]" + b_uuid_path="[null]" + b_language="[null]" + b_long_name="[null]" + b_module_uuid="[null]" + b_module_uuid_path="[null]" + b_name="[null]" + b_path="[null]" + b_qualifier="[null]" + /> + + <!-- unit test file --> + <projects organization_uuid="org1" + uuid="TEST_FILE_UUID" + uuid_path=".PROJECT_UUID.DIR_UUID." + project_uuid="PROJECT_UUID" + module_uuid="PROJECT_UUID" + module_uuid_path=".PROJECT_UUID." + main_branch_project_uuid="[null]" + created_at="[null]" + long_name="[null]" + scope="FIL" + qualifier="UTS" + kee="project:my/dir/FileTest.java" + name="my/dir/FileTest.java" + description="[null]" + private="[false]" + language="java" + copy_component_uuid="[null]" + developer_uuid="[null]" + path="[null]" + deprecated_kee="[null]" + authorization_updated_at="[null]" + id="4" + enabled="[true]" + root_uuid="PROJECT_UUID" + tags="[null]" b_changed="[false]" b_copy_component_uuid="[null]" b_description="[null]" @@ -129,7 +163,7 @@ What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 <!-- do not purge last snapshots --> <snapshots id="1" uuid="u1" - component_uuid="ABCD" + component_uuid="PROJECT_UUID" status="P" islast="[true]" purge_status="[null]" @@ -153,10 +187,75 @@ What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 version="[null]" /> + <project_measures id="1" + analysis_uuid="u1" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="PROJECT_UUID"/> + <project_measures id="2" + analysis_uuid="u1" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="DIR_UUID"/> + <project_measures id="3" + analysis_uuid="u1" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="FILE_UUID"/> + <project_measures id="4" + analysis_uuid="u1" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="TEST_FILE_UUID"/> + <!-- snapshots to be purged --> <snapshots id="4" - uuid="u4" - component_uuid="ABCD" + uuid="u2" + component_uuid="PROJECT_UUID" status="P" islast="[false]" purge_status="1" @@ -180,4 +279,69 @@ What has been changed : purge_status=1 on snapshot 4 (PRJ) and snapshots 5 and 6 version="[null]" /> + <project_measures id="5" + analysis_uuid="u2" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="PROJECT_UUID"/> + <!--<project_measures id="6"--> + <!--analysis_uuid="u2"--> + <!--metric_id="10"--> + <!--value="[null]"--> + <!--text_value="[null]"--> + <!--measure_data="[null]"--> + <!--variation_value_1="[null]"--> + <!--variation_value_2="[null]"--> + <!--variation_value_3="[null]"--> + <!--variation_value_4="[null]"--> + <!--variation_value_5="[null]"--> + <!--alert_status="[null]"--> + <!--alert_text="[null]"--> + <!--person_id="[null]"--> + <!--description="[null]"--> + <!--component_uuid="DIR_UUID"/>--> + <!--<project_measures id="7"--> + <!--analysis_uuid="u2"--> + <!--metric_id="10"--> + <!--value="[null]"--> + <!--text_value="[null]"--> + <!--measure_data="[null]"--> + <!--variation_value_1="[null]"--> + <!--variation_value_2="[null]"--> + <!--variation_value_3="[null]"--> + <!--variation_value_4="[null]"--> + <!--variation_value_5="[null]"--> + <!--alert_status="[null]"--> + <!--alert_text="[null]"--> + <!--person_id="[null]"--> + <!--description="[null]"--> + <!--component_uuid="FILE_UUID"/>--> + <!--<project_measures id="8"--> + <!--analysis_uuid="u2"--> + <!--metric_id="10"--> + <!--value="[null]"--> + <!--text_value="[null]"--> + <!--measure_data="[null]"--> + <!--variation_value_1="[null]"--> + <!--variation_value_2="[null]"--> + <!--variation_value_3="[null]"--> + <!--variation_value_4="[null]"--> + <!--variation_value_5="[null]"--> + <!--alert_status="[null]"--> + <!--alert_text="[null]"--> + <!--person_id="[null]"--> + <!--description="[null]"--> + <!--component_uuid="TEST_FILE_UUID"/>--> + </dataset> diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles.xml index c6f8da44917..ff62231bcb5 100644 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles.xml +++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/purge/PurgeDaoTest/shouldDeleteHistoricalDataOfDirectoriesAndFiles.xml @@ -2,9 +2,9 @@ <!-- the project --> <projects organization_uuid="org1" - uuid="ABCD" + uuid="PROJECT_UUID" uuid_path="." - project_uuid="ABCD" + project_uuid="PROJECT_UUID" module_uuid="[null]" module_uuid_path="." main_branch_project_uuid="[null]" @@ -24,8 +24,10 @@ authorization_updated_at="[null]" id="1" enabled="[true]" - root_uuid="ABCD" + root_uuid="PROJECT_UUID" + tags="[null]" b_changed="[false]" + b_copy_component_uuid="[null]" b_description="[null]" b_enabled="[false]" b_uuid_path="[null]" @@ -40,10 +42,10 @@ <!-- the directory --> <projects organization_uuid="org1" - uuid="EFGH" - uuid_path=".ABCD." - project_uuid="ABCD" - module_uuid="ABCD" + uuid="DIR_UUID" + uuid_path=".PROJECT_UUID." + project_uuid="PROJECT_UUID" + module_uuid="PROJECT_UUID" module_uuid_path="." main_branch_project_uuid="[null]" created_at="[null]" @@ -62,8 +64,10 @@ authorization_updated_at="[null]" id="2" enabled="[true]" - root_uuid="ABCD" + root_uuid="PROJECT_UUID" + tags="[null]" b_changed="[false]" + b_copy_component_uuid="[null]" b_description="[null]" b_enabled="[false]" b_uuid_path="[null]" @@ -78,11 +82,11 @@ <!-- the file --> <projects organization_uuid="org1" - uuid="GHIJ" - uuid_path=".ABCD.EFGH." - project_uuid="ABCD" - module_uuid="ABCD" - module_uuid_path=".ABCD." + uuid="FILE_UUID" + uuid_path=".PROJECT_UUID.DIR_UUID." + project_uuid="PROJECT_UUID" + module_uuid="PROJECT_UUID" + module_uuid_path=".PROJECT_UUID." main_branch_project_uuid="[null]" created_at="[null]" long_name="[null]" @@ -100,8 +104,50 @@ authorization_updated_at="[null]" id="3" enabled="[true]" - root_uuid="ABCD" + root_uuid="PROJECT_UUID" + tags="[null]" b_changed="[false]" + b_copy_component_uuid="[null]" + b_description="[null]" + b_enabled="[false]" + b_uuid_path="[null]" + b_language="[null]" + b_long_name="[null]" + b_module_uuid="[null]" + b_module_uuid_path="[null]" + b_name="[null]" + b_path="[null]" + b_qualifier="[null]" + /> + + <!-- unit test file --> + <projects organization_uuid="org1" + uuid="TEST_FILE_UUID" + uuid_path=".PROJECT_UUID.DIR_UUID." + project_uuid="PROJECT_UUID" + module_uuid="PROJECT_UUID" + module_uuid_path=".PROJECT_UUID." + main_branch_project_uuid="[null]" + created_at="[null]" + long_name="[null]" + scope="FIL" + qualifier="UTS" + kee="project:my/dir/FileTest.java" + name="my/dir/FileTest.java" + description="[null]" + private="[false]" + language="java" + copy_component_uuid="[null]" + developer_uuid="[null]" + path="[null]" + deprecated_kee="[null]" + authorization_updated_at="[null]" + id="4" + enabled="[true]" + root_uuid="PROJECT_UUID" + tags="[null]" + b_changed="[false]" + b_copy_component_uuid="[null]" b_description="[null]" b_enabled="[false]" b_uuid_path="[null]" @@ -117,7 +163,7 @@ <!-- do not purge last snapshots --> <snapshots id="1" uuid="u1" - component_uuid="ABCD" + component_uuid="PROJECT_UUID" status="P" islast="[true]" purge_status="[null]" @@ -141,10 +187,75 @@ version="[null]" /> + <project_measures id="1" + analysis_uuid="u1" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="PROJECT_UUID"/> + <project_measures id="2" + analysis_uuid="u1" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="DIR_UUID"/> + <project_measures id="3" + analysis_uuid="u1" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="FILE_UUID"/> + <project_measures id="4" + analysis_uuid="u1" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="TEST_FILE_UUID"/> + <!-- snapshots to be purged --> <snapshots id="4" - uuid="u4" - component_uuid="ABCD" + uuid="u2" + component_uuid="PROJECT_UUID" status="P" islast="[false]" purge_status="[null]" @@ -168,4 +279,69 @@ version="[null]" /> + <project_measures id="5" + analysis_uuid="u2" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="PROJECT_UUID"/> + <project_measures id="6" + analysis_uuid="u2" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="DIR_UUID"/> + <project_measures id="7" + analysis_uuid="u2" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="FILE_UUID"/> + <project_measures id="8" + analysis_uuid="u2" + metric_id="10" + value="[null]" + text_value="[null]" + measure_data="[null]" + variation_value_1="[null]" + variation_value_2="[null]" + variation_value_3="[null]" + variation_value_4="[null]" + variation_value_5="[null]" + alert_status="[null]" + alert_text="[null]" + person_id="[null]" + description="[null]" + component_uuid="TEST_FILE_UUID"/> + </dataset> diff --git a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v60/PopulateAnalysisUuidOnMeasures.java b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v60/PopulateAnalysisUuidOnMeasures.java index c7eca704768..d68fd020771 100644 --- a/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v60/PopulateAnalysisUuidOnMeasures.java +++ b/server/sonar-db-migration/src/main/java/org/sonar/server/platform/db/migration/version/v60/PopulateAnalysisUuidOnMeasures.java @@ -44,11 +44,6 @@ public class PopulateAnalysisUuidOnMeasures extends DataChange { massUpdate.select("select distinct m.snapshot_id as sId, s.root_snapshot_id as rootSid " + "from project_measures m " + "inner join snapshots s on m.snapshot_id = s.id " + - "where m.analysis_uuid is null " + - "union " + - "select distinct m.snapshot_id as sId, s.root_snapshot_id as rootSid " + - "from project_measures m " + - "inner join snapshots s on m.snapshot_id=s.id " + "where m.analysis_uuid is null" ); massUpdate.update("update project_measures set analysis_uuid=? where snapshot_id = ? and analysis_uuid is null"); diff --git a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v60/PopulateAnalysisUuidOnMeasuresTest.java b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v60/PopulateAnalysisUuidOnMeasuresTest.java index 023793635c6..eb274166294 100644 --- a/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v60/PopulateAnalysisUuidOnMeasuresTest.java +++ b/server/sonar-db-migration/src/test/java/org/sonar/server/platform/db/migration/version/v60/PopulateAnalysisUuidOnMeasuresTest.java @@ -81,7 +81,7 @@ public class PopulateAnalysisUuidOnMeasuresTest { assertThat(rows.get("analysisUuid")).isEqualTo(expectedAnalysisUuid); } - private String insertSnapshot(long id, String uuid, String qualifier, @Nullable Long rootSnapshotId) { + private void insertSnapshot(long id, String uuid, String qualifier, @Nullable Long rootSnapshotId) { int depth; switch (qualifier) { case "TRK": @@ -108,7 +108,6 @@ public class PopulateAnalysisUuidOnMeasuresTest { "ROOT_SNAPSHOT_ID", rootSnapshotId != null ? valueOf(rootSnapshotId) : null, "QUALIFIER", qualifier, "DEPTH", valueOf(depth)); - return uuid; } private void insertMeasure(long id, long snapshotId) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportAction.java index 50f907490eb..cea5b11724e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualityprofile/ws/ExportAction.java @@ -89,7 +89,7 @@ public class ExportAction implements QProfileWsAction { action.createParam(PARAM_QUALITY_PROFILE) .setDescription("Quality profile name to export. If left empty, the default profile for the language is exported. If this parameter is set, '%s' must not be set.", PARAM_KEY) - .setDeprecatedKey("profileName", "6.6") + .setDeprecatedKey("name", "6.6") .setExampleValue("My Sonar way"); action.createParam(PARAM_LANGUAGE) diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/DatabaseSettingLoader.java b/server/sonar-server/src/main/java/org/sonar/server/setting/DatabaseSettingLoader.java index 7e4203adae4..c8be9a21f24 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/setting/DatabaseSettingLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/setting/DatabaseSettingLoader.java @@ -19,7 +19,8 @@ */ package org.sonar.server.setting; -import com.google.common.collect.ImmutableMap; +import java.util.Map; +import org.sonar.core.util.stream.MoreCollectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.property.PropertyDto; @@ -44,10 +45,11 @@ public class DatabaseSettingLoader implements SettingLoader { } @Override - public void loadAll(ImmutableMap.Builder<String, String> appendTo) { + public Map<String, String> loadAll() { try (DbSession dbSession = dbClient.openSession(false)) { - dbClient.propertiesDao().selectGlobalProperties(dbSession) - .forEach(p -> appendTo.put(p.getKey(), defaultString(p.getValue()))); + return dbClient.propertiesDao().selectGlobalProperties(dbSession) + .stream() + .collect(MoreCollectors.uniqueIndex(PropertyDto::getKey, p -> defaultString(p.getValue()))); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/NopSettingLoader.java b/server/sonar-server/src/main/java/org/sonar/server/setting/NopSettingLoader.java index 4c494e34519..e161d5f090e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/setting/NopSettingLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/setting/NopSettingLoader.java @@ -19,7 +19,8 @@ */ package org.sonar.server.setting; -import com.google.common.collect.ImmutableMap; +import java.util.Collections; +import java.util.Map; public class NopSettingLoader implements SettingLoader { @Override @@ -28,8 +29,8 @@ public class NopSettingLoader implements SettingLoader { } @Override - public void loadAll(ImmutableMap.Builder<String, String> appendTo) { - // nothing to load + public Map<String, String> loadAll() { + return Collections.emptyMap(); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/SettingLoader.java b/server/sonar-server/src/main/java/org/sonar/server/setting/SettingLoader.java index 9115e7da8c8..49758eac29b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/setting/SettingLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/setting/SettingLoader.java @@ -19,7 +19,7 @@ */ package org.sonar.server.setting; -import com.google.common.collect.ImmutableMap; +import java.util.Map; import javax.annotation.CheckForNull; public interface SettingLoader { @@ -27,6 +27,6 @@ public interface SettingLoader { @CheckForNull String load(String key); - void loadAll(ImmutableMap.Builder<String, String> appendTo); + Map<String,String> loadAll(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/setting/ThreadLocalSettings.java b/server/sonar-server/src/main/java/org/sonar/server/setting/ThreadLocalSettings.java index a12c4963e02..9a131fb7ed5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/setting/ThreadLocalSettings.java +++ b/server/sonar-server/src/main/java/org/sonar/server/setting/ThreadLocalSettings.java @@ -20,7 +20,6 @@ package org.sonar.server.setting; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableMap; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -36,11 +35,12 @@ import org.sonar.api.config.Settings; import org.sonar.api.server.ServerSide; import static com.google.common.base.Preconditions.checkState; +import static java.util.Collections.unmodifiableMap; import static java.util.Objects.requireNonNull; /** - * Merge of {@link SystemSettings} and the global properties stored in the db table "properties". These - * settings do not contain the settings specific to a project. + * Merge of system settings (including conf/sonar.properties) and the global properties stored + * in the db table "properties". These settings do not contain the settings specific to a project. * * <p> * System settings have precedence on others. @@ -167,21 +167,19 @@ public class ThreadLocalSettings extends Settings { @Override public Map<String, String> getProperties() { - ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); - loadAll(builder); - systemProps.forEach((key, value) -> builder.put((String) key, (String) value)); - return builder.build(); + Map<String, String> result = new HashMap<>(); + loadAll(result); + systemProps.forEach((key, value) -> result.put((String) key, (String) value)); + return unmodifiableMap(result); } - private void loadAll(ImmutableMap.Builder<String, String> builder) { + private void loadAll(Map<String, String> appendTo) { try { - ImmutableMap.Builder<String, String> cacheBuilder = ImmutableMap.builder(); - settingLoader.loadAll(cacheBuilder); - Map<String, String> cache = cacheBuilder.build(); - builder.putAll(cache); + Map<String, String> cache = settingLoader.loadAll(); + appendTo.putAll(cache); getPropertiesDbFailureCache = cache; } catch (PersistenceException e) { - builder.putAll(getPropertiesDbFailureCache); + appendTo.putAll(getPropertiesDbFailureCache); } } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java index 55f46efe64e..7a08c259b7a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualityprofile/ws/ExportActionTest.java @@ -48,8 +48,8 @@ import org.sonar.server.ws.WsActionTester; import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; -import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE; import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_KEY; +import static org.sonarqube.ws.client.qualityprofile.QualityProfileWsParameters.PARAM_LANGUAGE; public class ExportActionTest { @@ -74,14 +74,19 @@ public class ExportActionTest { assertThat(definition.isPost()).isFalse(); assertThat(definition.isInternal()).isFalse(); assertThat(definition.params()).extracting(WebService.Param::key).containsExactlyInAnyOrder("key", "language", "qualityProfile", "organization"); + WebService.Param organizationParam = definition.param("organization"); assertThat(organizationParam.since()).isEqualTo("6.4"); assertThat(organizationParam.isInternal()).isTrue(); + WebService.Param key = definition.param("key"); assertThat(key.since()).isEqualTo("6.5"); assertThat(key.deprecatedSince()).isEqualTo("6.6"); + WebService.Param name = definition.param("qualityProfile"); assertThat(name.deprecatedSince()).isNullOrEmpty(); + assertThat(name.deprecatedKey()).isEqualTo("name"); + WebService.Param language = definition.param("language"); assertThat(language.deprecatedSince()).isNullOrEmpty(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/setting/DatabaseSettingLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/setting/DatabaseSettingLoaderTest.java index 922554bec55..d14c66605ce 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/setting/DatabaseSettingLoaderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/setting/DatabaseSettingLoaderTest.java @@ -19,7 +19,7 @@ */ package org.sonar.server.setting; -import com.google.common.collect.ImmutableMap; +import java.util.Map; import org.junit.Rule; import org.junit.Test; import org.sonar.api.utils.System2; @@ -49,6 +49,7 @@ public class DatabaseSettingLoaderTest { @Test public void null_value_in_db_is_considered_as_empty_string() { insertPropertyIntoDb(A_KEY, null); + assertThat(underTest.load(A_KEY)).isEqualTo(""); } @@ -60,19 +61,19 @@ public class DatabaseSettingLoaderTest { @Test public void test_loadAll_with_no_properties() { - ImmutableMap.Builder<String, String> map = ImmutableMap.builder(); - underTest.loadAll(map); - assertThat(map.build().isEmpty()).isTrue(); + Map<String, String> map = underTest.loadAll(); + assertThat(map).isEmpty(); } - @Test - public void test_loadAll() { - insertPropertyIntoDb("foo", "1"); - insertPropertyIntoDb("bar", "2"); - ImmutableMap.Builder<String, String> map = ImmutableMap.builder(); - underTest.loadAll(map); - assertThat(map.build()).containsOnly(entry("foo", "1"), entry("bar", "2")); - } + @Test + public void test_loadAll() { + insertPropertyIntoDb("foo", "1"); + insertPropertyIntoDb("bar", "2"); + + Map<String, String> map = underTest.loadAll(); + + assertThat(map).containsOnly(entry("foo", "1"), entry("bar", "2")); + } private void insertPropertyIntoDb(String key, String value) { dbTester.getDbClient().propertiesDao().saveProperty(new PropertyDto().setKey(key).setValue(value)); diff --git a/server/sonar-server/src/test/java/org/sonar/server/setting/NopSettingLoaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/setting/NopSettingLoaderTest.java index 329abda074e..798e534f4c8 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/setting/NopSettingLoaderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/setting/NopSettingLoaderTest.java @@ -19,9 +19,7 @@ */ package org.sonar.server.setting; -import com.google.common.collect.ImmutableMap; import org.junit.Test; -import org.sonar.server.setting.NopSettingLoader; import static org.assertj.core.api.Assertions.assertThat; @@ -33,8 +31,6 @@ public class NopSettingLoaderTest { public void do_nothing() { assertThat(underTest.load("foo")).isNull(); - ImmutableMap.Builder<String,String> map = ImmutableMap.builder(); - underTest.loadAll(map); - assertThat(map.build()).isEmpty(); + assertThat(underTest.loadAll()).isEmpty(); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/setting/ThreadLocalSettingsTest.java b/server/sonar-server/src/test/java/org/sonar/server/setting/ThreadLocalSettingsTest.java index 9dc3e4df4e7..4884c5fa8e7 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/setting/ThreadLocalSettingsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/setting/ThreadLocalSettingsTest.java @@ -35,11 +35,11 @@ import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.sonar.api.config.PropertyDefinitions; +import static java.util.Collections.unmodifiableMap; import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.data.MapEntry.entry; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -109,6 +109,18 @@ public class ThreadLocalSettingsTest { assertThat(underTest.get("foo")).isNotPresent(); } + /** + * SONAR-8216 System info page fails when a setting is defined both in sonar.properties and in DB + */ + @Test + public void getProperties_does_not_fail_on_duplicated_key() { + insertPropertyIntoDb("foo", "from_db"); + underTest = create(ImmutableMap.of("foo", "from_system")); + + assertThat(underTest.get("foo")).hasValue("from_system"); + assertThat(underTest.getProperties().get("foo")).isEqualTo("from_system"); + } + @Test public void load_encryption_secret_key_from_system_properties() throws Exception { File secretKey = temp.newFile(); @@ -259,7 +271,7 @@ public class ThreadLocalSettingsTest { public void getProperties_return_empty_if_DB_error_on_first_call_ever_out_of_thread_cache() { SettingLoader settingLoaderMock = mock(SettingLoader.class); PersistenceException toBeThrown = new PersistenceException("Faking an error connecting to DB"); - doThrow(toBeThrown).when(settingLoaderMock).loadAll(any(ImmutableMap.Builder.class)); + doThrow(toBeThrown).when(settingLoaderMock).loadAll(); underTest = new ThreadLocalSettings(new PropertyDefinitions(), new Properties(), settingLoaderMock); assertThat(underTest.getProperties()) @@ -270,7 +282,7 @@ public class ThreadLocalSettingsTest { public void getProperties_returns_empty_if_DB_error_on_first_call_ever_in_thread_cache() { SettingLoader settingLoaderMock = mock(SettingLoader.class); PersistenceException toBeThrown = new PersistenceException("Faking an error connecting to DB"); - doThrow(toBeThrown).when(settingLoaderMock).loadAll(any(ImmutableMap.Builder.class)); + doThrow(toBeThrown).when(settingLoaderMock).loadAll(); underTest = new ThreadLocalSettings(new PropertyDefinitions(), new Properties(), settingLoaderMock); underTest.load(); @@ -285,18 +297,11 @@ public class ThreadLocalSettingsTest { String value2 = randomAlphanumeric(5); SettingLoader settingLoaderMock = mock(SettingLoader.class); PersistenceException toBeThrown = new PersistenceException("Faking an error connecting to DB"); - doAnswer(invocationOnMock -> { - ImmutableMap.Builder<String, String> builder = (ImmutableMap.Builder<String, String>) invocationOnMock.getArguments()[0]; - builder.put(key, value1); - return null; - }).doThrow(toBeThrown) - .doAnswer(invocationOnMock -> { - ImmutableMap.Builder<String, String> builder = (ImmutableMap.Builder<String, String>) invocationOnMock.getArguments()[0]; - builder.put(key, value2); - return null; - }) + doAnswer(invocationOnMock -> ImmutableMap.of(key, value1)) + .doThrow(toBeThrown) + .doAnswer(invocationOnMock -> ImmutableMap.of(key, value2)) .when(settingLoaderMock) - .loadAll(any(ImmutableMap.Builder.class)); + .loadAll(); underTest = new ThreadLocalSettings(new PropertyDefinitions(), new Properties(), settingLoaderMock); underTest.load(); @@ -394,8 +399,8 @@ public class ThreadLocalSettingsTest { } @Override - public void loadAll(ImmutableMap.Builder<String, String> appendTo) { - appendTo.putAll(map); + public Map<String, String> loadAll() { + return unmodifiableMap(map); } } } |