]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-5628 - Compute Engine - Move DbCleaner
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Thu, 23 Oct 2014 15:15:00 +0000 (17:15 +0200)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Mon, 27 Oct 2014 08:08:39 +0000 (09:08 +0100)
77 files changed:
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DbCleanerPlugin.java
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DefaultPurgeTask.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DeprecatedDefaultPurgeTask.java [new file with mode: 0644]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/ProjectPurgePostJob.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/DbCleanerConstants.java
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/PurgeTask.java
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleaner.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilter.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filter.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filters.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Interval.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneFilter.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/package-info.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerPluginTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerTestUtils.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DefaultPurgeTaskTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilterTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/IntervalTest.java [deleted file]
plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneFilterTest.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportQueue.java
server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportStep.java [deleted file]
server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportTaskLauncher.java
server/sonar-server/src/main/java/org/sonar/server/computation/ComputationService.java
server/sonar-server/src/main/java/org/sonar/server/computation/ComputationStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/ComputationStepRegistry.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/DbCleanerStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/GetAndSetProjectStep.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/computation/IndexProjectIssuesStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/SwitchSnapshotStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/SynchronizeProjectPermissionsStep.java
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportLogMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/AnalysisReportQueueMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/ComputationServiceTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/ComputationStepRegistryTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/DbCleanStepTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/DbCleanerStepTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/GetAndSetProjectStepTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/computation/SynchronizeProjectPermissionsStepMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/db/AnalysisReportDaoTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/ws/ActiveAnalysisReportsActionTest.java
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/any-analysis-reports.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/insert-result.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_analysis_report.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_available_analysis.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_available_analysis_but_another_busy_on_same_project.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/one_busy_report_analysis.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select-with-no-available-report.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select_oldest_available_report.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/select_oldest_available_report_with_working_reports_older.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/three_analysis_reports.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending-result.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/db/AnalysisReportDaoTest/update-all-to-status-pending.xml
server/sonar-server/src/test/resources/org/sonar/server/computation/ws/ActiveAnalysisReportsActionTest/list_active_reports.json
sonar-core/src/main/java/org/sonar/core/computation/db/AnalysisReportDto.java
sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DbCleanerConstants.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DbCleanerProperties.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DeleteAllFilter.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/Filter.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/Filters.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/Interval.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/KeepOneFilter.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/package-info.java [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/config/CorePropertyDefinitions.java
sonar-core/src/main/resources/org/sonar/core/computation/db/AnalysisReportMapper.xml
sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DbCleanerPropertiesTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DbCleanerTestUtils.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleanerTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/DeleteAllFilterTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/IntervalTest.java [new file with mode: 0644]
sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/KeepOneFilterTest.java [new file with mode: 0644]

index 01397e6be89f77401980d0100eb4747c5ed20fe1..56cad6f8a8443b199e8c250893b0cfada6eb8a57 100644 (file)
  * 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.plugins.dbcleaner;
 
 import com.google.common.collect.ImmutableList;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.PropertyType;
+import com.google.common.collect.Lists;
 import org.sonar.api.SonarPlugin;
 import org.sonar.api.config.PropertyDefinition;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
-import org.sonar.plugins.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
 
-import java.util.Arrays;
 import java.util.List;
 
+@Deprecated
 public final class DbCleanerPlugin extends SonarPlugin {
 
+  static List<PropertyDefinition> propertyDefinitions() {
+    return Lists.newArrayList();
+  }
+
   @Override
   public List getExtensions() {
-    return ImmutableList.builder().add(DefaultPeriodCleaner.class, DefaultPurgeTask.class, ProjectPurgePostJob.class)
+    return ImmutableList.builder().add(DefaultPeriodCleaner.class, DeprecatedDefaultPurgeTask.class)
       .addAll(propertyDefinitions()).build();
   }
-
-  static List<PropertyDefinition> propertyDefinitions() {
-    return Arrays.asList(
-      PropertyDefinition.builder(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)
-        .defaultValue("true")
-        .name("Clean directory/package history")
-        .description("If set to true, no history is kept at directory/package level. Setting this to false can cause database bloat.")
-        .type(PropertyType.BOOLEAN)
-        .onQualifiers(Qualifiers.PROJECT)
-        .category(CoreProperties.CATEGORY_GENERAL)
-        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
-        .index(1)
-        .build(),
-
-      PropertyDefinition.builder(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES)
-        .defaultValue("30")
-        .name("Delete closed issues after")
-        .description("Issues that have been closed for more than this number of days will be deleted.")
-        .type(PropertyType.INTEGER)
-        .onQualifiers(Qualifiers.PROJECT)
-        .category(CoreProperties.CATEGORY_GENERAL)
-        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
-        .index(2)
-        .build(),
-
-      PropertyDefinition.builder(DbCleanerConstants.HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY)
-        .defaultValue("24")
-        .name("Keep only one snapshot a day after")
-        .description("After this number of hours, if there are several snapshots during the same day, "
-          + "the DbCleaner keeps the most recent one and fully deletes the other ones.")
-        .type(PropertyType.INTEGER)
-        .onQualifiers(Qualifiers.PROJECT)
-        .category(CoreProperties.CATEGORY_GENERAL)
-        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
-        .index(3)
-        .build(),
-
-      PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK)
-        .defaultValue("4")
-        .name("Keep only one snapshot a week after")
-        .description("After this number of weeks, if there are several snapshots during the same week, "
-          + "the DbCleaner keeps the most recent one and fully deletes the other ones")
-        .type(PropertyType.INTEGER)
-        .onQualifiers(Qualifiers.PROJECT)
-        .category(CoreProperties.CATEGORY_GENERAL)
-        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
-        .index(4)
-        .build(),
-
-      PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH)
-        .defaultValue("52")
-        .name("Keep only one snapshot a month after")
-        .description("After this number of weeks, if there are several snapshots during the same month, "
-          + "the DbCleaner keeps the most recent one and fully deletes the other ones.")
-        .type(PropertyType.INTEGER)
-        .onQualifiers(Qualifiers.PROJECT)
-        .category(CoreProperties.CATEGORY_GENERAL)
-        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
-        .index(5)
-        .build(),
-
-      PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS)
-        .defaultValue("260")
-        .name("Delete all snapshots after")
-        .description("After this number of weeks, all snapshots are fully deleted.")
-        .type(PropertyType.INTEGER)
-        .onQualifiers(Qualifiers.PROJECT)
-        .category(CoreProperties.CATEGORY_GENERAL)
-        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
-        .index(6)
-        .build()
-      );
-  }
 }
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DefaultPurgeTask.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DefaultPurgeTask.java
deleted file mode 100644 (file)
index 5636515..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.plugins.dbcleaner;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Scopes;
-import org.sonar.api.utils.TimeUtils;
-import org.sonar.core.purge.PurgeConfiguration;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeProfiler;
-import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
-import org.sonar.plugins.dbcleaner.api.PurgeTask;
-import org.sonar.plugins.dbcleaner.period.DefaultPeriodCleaner;
-
-/**
- * @since 2.14
- */
-public class DefaultPurgeTask implements PurgeTask {
-  private static final Logger LOG = LoggerFactory.getLogger(DefaultPurgeTask.class);
-
-  private PurgeDao purgeDao;
-  private Settings settings;
-  private DefaultPeriodCleaner periodCleaner;
-  private final PurgeProfiler profiler;
-
-  public DefaultPurgeTask(PurgeDao purgeDao, Settings settings, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler) {
-    this.purgeDao = purgeDao;
-    this.settings = settings;
-    this.periodCleaner = periodCleaner;
-    this.profiler = profiler;
-  }
-
-  @Override
-  public PurgeTask delete(long resourceId) {
-    purgeDao.deleteResourceTree(resourceId);
-    return this;
-  }
-
-  @Override
-  public PurgeTask purge(long resourceId) {
-    long start = System.currentTimeMillis();
-    profiler.reset();
-    cleanHistoricalData(resourceId);
-    doPurge(resourceId);
-    if (settings.getBoolean(CoreProperties.PROFILING_LOG_PROPERTY)) {
-      long duration = System.currentTimeMillis() - start;
-      LOG.info("\n -------- Profiling for purge: " + TimeUtils.formatDuration(duration) + " --------\n");
-      profiler.dump(duration, LOG);
-      LOG.info("\n -------- End of profiling for purge --------\n");
-    }
-    return this;
-  }
-
-  private void cleanHistoricalData(long resourceId) {
-    try {
-      periodCleaner.clean(resourceId);
-    } catch (Exception e) {
-      // purge errors must no fail the batch
-      LOG.error("Fail to clean historical data [id=" + resourceId + "]", e);
-    }
-  }
-
-  private void doPurge(long resourceId) {
-    try {
-      purgeDao.purge(newConf(resourceId));
-    } catch (Exception e) {
-      // purge errors must no fail the batch
-      LOG.error("Fail to purge data [id=" + resourceId + "]", e);
-    }
-  }
-
-  private PurgeConfiguration newConf(long resourceId) {
-    String[] scopes = new String[] {Scopes.FILE};
-    if (settings.getBoolean(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)) {
-      scopes = new String[] {Scopes.DIRECTORY, Scopes.FILE};
-    }
-    return new PurgeConfiguration(resourceId, scopes, settings.getInt(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES));
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DeprecatedDefaultPurgeTask.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/DeprecatedDefaultPurgeTask.java
new file mode 100644 (file)
index 0000000..50e340b
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.plugins.dbcleaner;
+
+import org.sonar.api.config.Settings;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeProfiler;
+import org.sonar.plugins.dbcleaner.api.PurgeTask;
+
+/**
+ * @since 2.14
+ */
+@Deprecated
+public class DeprecatedDefaultPurgeTask implements PurgeTask {
+  private final DefaultPurgeTask defaultPurgeTask;
+
+  public DeprecatedDefaultPurgeTask(PurgeDao purgeDao, Settings settings, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler) {
+    defaultPurgeTask = new DefaultPurgeTask(purgeDao, settings, periodCleaner, profiler);
+  }
+
+  @Override
+  public DeprecatedDefaultPurgeTask delete(long resourceId) {
+    defaultPurgeTask.delete(resourceId);
+    return this;
+  }
+
+  @Override
+  public DeprecatedDefaultPurgeTask purge(long resourceId) {
+    defaultPurgeTask.purge(resourceId);
+    return this;
+  }
+}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/ProjectPurgePostJob.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/ProjectPurgePostJob.java
deleted file mode 100644 (file)
index 1a412bc..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.plugins.dbcleaner;
-
-import org.sonar.api.batch.PostJob;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.resources.Project;
-import org.sonar.core.DryRunIncompatible;
-import org.sonar.plugins.dbcleaner.api.PurgeTask;
-
-@DryRunIncompatible
-public class ProjectPurgePostJob implements PostJob {
-
-  private PurgeTask purgeTask;
-
-  public ProjectPurgePostJob(PurgeTask purgeTask) {
-    this.purgeTask = purgeTask;
-  }
-
-  @Override
-  public void executeOn(final Project project, SensorContext context) {
-    purgeTask.purge(project.getId());
-  }
-}
index 7f77420e2f8ff7d11bf54019befc9962edaaf2ac..881fca768a3400969c9e962bd9f3d1f0239d1d34 100644 (file)
  */
 package org.sonar.plugins.dbcleaner.api;
 
-public interface DbCleanerConstants {
-
-  String PLUGIN_KEY = "dbcleaner";
-  String PLUGIN_NAME = "DbCleaner";
-  String PROPERTY_CLEAN_DIRECTORY = "sonar.dbcleaner.cleanDirectory";
-
-  String HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY = "sonar.dbcleaner.hoursBeforeKeepingOnlyOneSnapshotByDay";
-  String WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK = "sonar.dbcleaner.weeksBeforeKeepingOnlyOneSnapshotByWeek";
-  String WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH = "sonar.dbcleaner.weeksBeforeKeepingOnlyOneSnapshotByMonth";
-  String WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS = "sonar.dbcleaner.weeksBeforeDeletingAllSnapshots";
-  String DAYS_BEFORE_DELETING_CLOSED_ISSUES = "sonar.dbcleaner.daysBeforeDeletingClosedIssues";
+@Deprecated
+public interface DbCleanerConstants extends org.sonar.core.computation.dbcleaner.DbCleanerConstants {
 }
index eec483cc45e883ad6e17020d57f670d719dfa91c..810608f606990406ddce417144f727db964f3396 100644 (file)
  */
 package org.sonar.plugins.dbcleaner.api;
 
-import org.sonar.api.task.TaskExtension;
-
 import com.google.common.annotations.Beta;
+import org.sonar.api.task.TaskExtension;
 
 /**
  * @since 2.14
  */
 @Beta
+@Deprecated
 public interface PurgeTask extends TaskExtension {
   /**
    * Purges the data related to a tree of resources.
-   *
+   * <p/>
    * Exceptions are logged and are not thrown again, so this method fails only on {@link Error}s.
    *
    * @param resourceId the root of the tree
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleaner.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleaner.java
deleted file mode 100644 (file)
index ade98c3..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.plugins.dbcleaner.period;
-
-import com.google.common.annotations.VisibleForTesting;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Project;
-import org.sonar.api.task.TaskExtension;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeSnapshotQuery;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.List;
-
-public class DefaultPeriodCleaner implements TaskExtension {
-
-  private static final Logger LOG = LoggerFactory.getLogger(DefaultPeriodCleaner.class);
-  private PurgeDao purgeDao;
-  private Settings settings;
-
-  public DefaultPeriodCleaner(PurgeDao purgeDao, Settings settings) {
-    this.purgeDao = purgeDao;
-    this.settings = settings;
-  }
-
-  public void purge(Project project, int projectSnapshotId) {
-    clean(project.getId());
-  }
-
-  public void clean(long projectId) {
-    doClean(projectId, new Filters(settings).all());
-  }
-
-  @VisibleForTesting
-  void doClean(long projectId, List<Filter> filters) {
-    List<PurgeableSnapshotDto> history = selectProjectSnapshots(projectId);
-    for (Filter filter : filters) {
-      filter.log();
-      delete(filter.filter(history));
-    }
-  }
-
-  private void delete(List<PurgeableSnapshotDto> snapshots) {
-    for (PurgeableSnapshotDto snapshot : snapshots) {
-      LOG.info("<- Delete snapshot: " + DateUtils.formatDateTime(snapshot.getDate()) + " [" + snapshot.getSnapshotId() + "]");
-      purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setRootSnapshotId(snapshot.getSnapshotId()));
-      purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setId(snapshot.getSnapshotId()));
-    }
-  }
-
-  private List<PurgeableSnapshotDto> selectProjectSnapshots(long resourceId) {
-    return purgeDao.selectPurgeableSnapshots(resourceId);
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilter.java
deleted file mode 100644 (file)
index 18a795e..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.plugins.dbcleaner.period;
-
-import com.google.common.collect.Lists;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.Date;
-import java.util.List;
-
-class DeleteAllFilter implements Filter {
-  private final Date before;
-
-  public DeleteAllFilter(Date before) {
-    this.before = before;
-  }
-
-  @Override
-  public List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) {
-    List<PurgeableSnapshotDto> result = Lists.newArrayList();
-    for (PurgeableSnapshotDto snapshot : history) {
-      if (snapshot.getDate().before(before)) {
-        result.add(snapshot);
-      }
-    }
-    return result;
-  }
-
-  @Override
-  public void log() {
-    LoggerFactory.getLogger(getClass()).info("-> Delete data prior to: " + DateUtils.formatDate(before));
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filter.java
deleted file mode 100644 (file)
index 4d4419b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.plugins.dbcleaner.period;
-
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.List;
-
-interface Filter {
-  List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> snapshots);
-
-  void log();
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filters.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Filters.java
deleted file mode 100644 (file)
index c291cd8..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.plugins.dbcleaner.period;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.lang.time.DateUtils;
-import org.sonar.api.config.Settings;
-import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-
-class Filters {
-  private final List<Filter> all = Lists.newArrayList();
-
-  Filters(Settings settings) {
-    Date dateToStartKeepingOneSnapshotByDay = getDateFromHours(settings, DbCleanerConstants.HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY);
-    Date dateToStartKeepingOneSnapshotByWeek = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK);
-    Date dateToStartKeepingOneSnapshotByMonth = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH);
-    Date dateToStartDeletingAllSnapshots = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS);
-
-    all.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByWeek, dateToStartKeepingOneSnapshotByDay, Calendar.DAY_OF_YEAR, "day"));
-    all.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByMonth, dateToStartKeepingOneSnapshotByWeek, Calendar.WEEK_OF_YEAR, "week"));
-    all.add(new KeepOneFilter(dateToStartDeletingAllSnapshots, dateToStartKeepingOneSnapshotByMonth, Calendar.MONTH, "month"));
-    all.add(new DeleteAllFilter(dateToStartDeletingAllSnapshots));
-  }
-
-  List<Filter> all() {
-    return all;
-  }
-
-  static Date getDateFromWeeks(Settings settings, String propertyKey) {
-    int weeks = settings.getInt(propertyKey);
-    return DateUtils.addWeeks(new Date(), -weeks);
-  }
-
-  static Date getDateFromHours(Settings settings, String propertyKey) {
-    int hours = settings.getInt(propertyKey);
-    return DateUtils.addHours(new Date(), -hours);
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Interval.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/Interval.java
deleted file mode 100644 (file)
index 18b02c3..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.plugins.dbcleaner.period;
-
-import com.google.common.collect.Lists;
-import org.apache.commons.lang.time.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.List;
-
-final class Interval {
-  List<PurgeableSnapshotDto> snapshots = Lists.newArrayList();
-
-  void add(PurgeableSnapshotDto snapshot) {
-    snapshots.add(snapshot);
-  }
-
-  List<PurgeableSnapshotDto> get() {
-    return snapshots;
-  }
-
-  int count() {
-    return snapshots.size();
-  }
-
-  static List<Interval> group(List<PurgeableSnapshotDto> snapshots, Date start, Date end, int calendarField) {
-    List<Interval> intervals = Lists.newArrayList();
-
-    GregorianCalendar calendar = new GregorianCalendar();
-    int lastYear = -1;
-    int lastFieldValue = -1;
-    Interval currentInterval = null;
-
-    for (PurgeableSnapshotDto snapshot : snapshots) {
-      if (!DateUtils.isSameDay(start, snapshot.getDate()) && snapshot.getDate().after(start) &&
-        (snapshot.getDate().before(end) || DateUtils.isSameDay(end, snapshot.getDate()))) {
-        calendar.setTime(snapshot.getDate());
-        int currentFieldValue = calendar.get(calendarField);
-        int currentYear = calendar.get(Calendar.YEAR);
-        if (lastYear!=currentYear || lastFieldValue != currentFieldValue) {
-          currentInterval = new Interval();
-          intervals.add(currentInterval);
-        }
-        lastFieldValue = currentFieldValue;
-        lastYear = currentYear;
-        if (currentInterval != null) {
-          currentInterval.add(snapshot);
-        }
-      }
-    }
-    return intervals;
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneFilter.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/KeepOneFilter.java
deleted file mode 100644 (file)
index 81249fd..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.plugins.dbcleaner.period;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Lists;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.Date;
-import java.util.List;
-
-class KeepOneFilter implements Filter {
-
-  private final Date start;
-  private final Date end;
-  private final int dateField;
-  private final String label;
-
-  KeepOneFilter(Date start, Date end, int calendarField, String label) {
-    this.start = start;
-    this.end = end;
-    this.dateField = calendarField;
-    this.label = label;
-  }
-
-  @Override
-  public List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) {
-    List<Interval> intervals = Interval.group(history, start, end, dateField);
-    List<PurgeableSnapshotDto> result = Lists.newArrayList();
-    for (Interval interval : intervals) {
-      appendSnapshotsToDelete(interval, result);
-    }
-
-    return result;
-  }
-
-  @Override
-  public void log() {
-    LoggerFactory.getLogger(getClass()).info("-> Keep one snapshot per " + label + " between " + DateUtils.formatDate(start) + " and " + DateUtils.formatDate(end));
-  }
-
-  private void appendSnapshotsToDelete(Interval interval, List<PurgeableSnapshotDto> toDelete) {
-    if (interval.count() > 1) {
-      List<PurgeableSnapshotDto> deletables = Lists.newArrayList();
-      List<PurgeableSnapshotDto> toKeep = Lists.newArrayList();
-      for (PurgeableSnapshotDto snapshot : interval.get()) {
-        if (isDeletable(snapshot)) {
-          deletables.add(snapshot);
-        } else {
-          toKeep.add(snapshot);
-        }
-      }
-
-      if (!toKeep.isEmpty()) {
-        toDelete.addAll(deletables);
-
-      } else if (deletables.size() > 1) {
-        // keep one snapshot
-        toDelete.addAll(deletables.subList(1, deletables.size()));
-      }
-    }
-  }
-
-  @VisibleForTesting
-  static boolean isDeletable(PurgeableSnapshotDto snapshot) {
-    return !snapshot.isLast() && !snapshot.hasEvents();
-  }
-
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/package-info.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/period/package-info.java
deleted file mode 100644 (file)
index f5b97cf..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- */
-
-@ParametersAreNonnullByDefault
-package org.sonar.plugins.dbcleaner.period;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerPluginTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerPluginTest.java
deleted file mode 100644 (file)
index da6ddc9..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.plugins.dbcleaner;
-
-import org.junit.Test;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class DbCleanerPluginTest {
-
-  @Test
-  public void shouldGetExtensions() {
-    assertThat(new DbCleanerPlugin().getExtensions()).hasSize(9);
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerTestUtils.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DbCleanerTestUtils.java
deleted file mode 100644 (file)
index 944c34b..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.plugins.dbcleaner;
-
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-public final class DbCleanerTestUtils {
-
-  private DbCleanerTestUtils() {
-  }
-
-  public static PurgeableSnapshotDto createSnapshotWithDate(long snapshotId, String date) {
-    PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto();
-    snapshot.setSnapshotId(snapshotId);
-    snapshot.setDate(DateUtils.parseDate(date));
-    return snapshot;
-  }
-
-  public static PurgeableSnapshotDto createSnapshotWithDateTime(long snapshotId, String datetime) {
-    PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto();
-    snapshot.setSnapshotId(snapshotId);
-    snapshot.setDate(DateUtils.parseDateTime(datetime));
-    return snapshot;
-  }
-
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DefaultPurgeTaskTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/DefaultPurgeTaskTest.java
deleted file mode 100644 (file)
index 7d6e48b..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.plugins.dbcleaner;
-
-import ch.qos.logback.classic.Logger;
-import org.junit.Test;
-import org.mockito.ArgumentMatcher;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Scopes;
-import org.sonar.core.purge.PurgeConfiguration;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeProfiler;
-import org.sonar.plugins.dbcleaner.api.DbCleanerConstants;
-import org.sonar.plugins.dbcleaner.period.DefaultPeriodCleaner;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class DefaultPurgeTaskTest {
-  @Test
-  public void shouldNotDeleteHistoricalDataOfDirectories() {
-    PurgeDao purgeDao = mock(PurgeDao.class);
-    Settings settings = new Settings(new PropertyDefinitions(DbCleanerPlugin.propertyDefinitions()));
-    settings.setProperty(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY, "false");
-    DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
-
-    task.purge(1L);
-
-    verify(purgeDao).purge(argThat(new ArgumentMatcher<PurgeConfiguration>() {
-      @Override
-      public boolean matches(Object o) {
-        PurgeConfiguration conf = (PurgeConfiguration) o;
-        return conf.rootProjectId() == 1L && conf.scopesWithoutHistoricalData().length == 1 && conf.scopesWithoutHistoricalData()[0].equals(Scopes.FILE);
-      }
-    }));
-  }
-
-  @Test
-  public void shouldDeleteHistoricalDataOfDirectoriesByDefault() {
-    PurgeDao purgeDao = mock(PurgeDao.class);
-    Settings settings = new Settings(new PropertyDefinitions(DbCleanerPlugin.propertyDefinitions()));
-    DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
-
-    task.purge(1L);
-
-    verify(purgeDao).purge(argThat(new ArgumentMatcher<PurgeConfiguration>() {
-      @Override
-      public boolean matches(Object o) {
-        PurgeConfiguration conf = (PurgeConfiguration) o;
-        return conf.rootProjectId() == 1L &&
-          conf.scopesWithoutHistoricalData().length == 2 &&
-          conf.scopesWithoutHistoricalData()[0].equals(Scopes.DIRECTORY) &&
-          conf.scopesWithoutHistoricalData()[1].equals(Scopes.FILE);
-      }
-    }));
-  }
-
-  @Test
-  public void shouldNotFailOnErrors() {
-    PurgeDao purgeDao = mock(PurgeDao.class);
-    when(purgeDao.purge(any(PurgeConfiguration.class))).thenThrow(new RuntimeException());
-    DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, new Settings(), mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
-
-    task.purge(1L);
-
-    verify(purgeDao, times(1)).purge(any(PurgeConfiguration.class));
-  }
-
-  @Test
-  public void shouldDumpProfiling() {
-    PurgeConfiguration conf = new PurgeConfiguration(1L, new String[0], 30);
-    PurgeDao purgeDao = mock(PurgeDao.class);
-    when(purgeDao.purge(conf)).thenThrow(new RuntimeException());
-    Settings settings = new Settings(new PropertyDefinitions(DbCleanerPlugin.propertyDefinitions()));
-    settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, true);
-    PurgeProfiler profiler = mock(PurgeProfiler.class);
-
-    DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), profiler);
-    task.purge(1L);
-
-    verify(profiler).dump(anyLong(), any(Logger.class));
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DefaultPeriodCleanerTest.java
deleted file mode 100644 (file)
index c252c3b..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.plugins.dbcleaner.period;
-
-import org.apache.commons.lang.ObjectUtils;
-import org.hamcrest.BaseMatcher;
-import org.junit.Test;
-import org.mockito.ArgumentMatcher;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.sonar.api.config.Settings;
-import org.sonar.core.purge.PurgeDao;
-import org.sonar.core.purge.PurgeSnapshotQuery;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.Arrays;
-import java.util.Date;
-
-import static org.mockito.Matchers.anyListOf;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class DefaultPeriodCleanerTest {
-
-
-  @Test
-  public void doClean() {
-    PurgeDao dao = mock(PurgeDao.class);
-    when(dao.selectPurgeableSnapshots(123L)).thenReturn(Arrays.asList(
-        new PurgeableSnapshotDto().setSnapshotId(999L).setDate(new Date())));
-    Filter filter1 = newLazyFilter();
-    Filter filter2 = newLazyFilter();
-
-    DefaultPeriodCleaner cleaner = new DefaultPeriodCleaner(dao, mock(Settings.class));
-    cleaner.doClean(123L, Arrays.asList(filter1, filter2));
-
-    verify(filter1).log();
-    verify(filter2).log();
-    verify(dao, times(2)).deleteSnapshots(argThat(newRootSnapshotQuery()));
-    verify(dao, times(2)).deleteSnapshots(argThat(newSnapshotIdQuery()));
-  }
-
-  private BaseMatcher<PurgeSnapshotQuery> newRootSnapshotQuery() {
-    return new ArgumentMatcher<PurgeSnapshotQuery>() {
-      @Override
-      public boolean matches(Object o) {
-        PurgeSnapshotQuery query = (PurgeSnapshotQuery) o;
-        return ObjectUtils.equals(query.getRootSnapshotId(), 999L);
-      }
-    };
-  }
-
-  private BaseMatcher<PurgeSnapshotQuery> newSnapshotIdQuery() {
-    return new ArgumentMatcher<PurgeSnapshotQuery>() {
-      @Override
-      public boolean matches(Object o) {
-        PurgeSnapshotQuery query = (PurgeSnapshotQuery) o;
-        return ObjectUtils.equals(query.getId(), 999L);
-      }
-    };
-  }
-
-  private Filter newLazyFilter() {
-    Filter filter1 = mock(Filter.class);
-    when(filter1.filter(anyListOf(PurgeableSnapshotDto.class))).thenAnswer(new Answer<Object>() {
-      public Object answer(InvocationOnMock invocation) throws Throwable {
-        return invocation.getArguments()[0];
-      }
-    });
-    return filter1;
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/DeleteAllFilterTest.java
deleted file mode 100644 (file)
index 12967c1..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.plugins.dbcleaner.period;
-
-import org.junit.Test;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-import org.sonar.plugins.dbcleaner.DbCleanerTestUtils;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class DeleteAllFilterTest {
-
-  @Test
-  public void shouldDeleteAllSnapshotsPriorToDate() {
-    Filter filter = new DeleteAllFilter(DateUtils.parseDate("2011-12-25"));
-
-    List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.asList(
-      DbCleanerTestUtils.createSnapshotWithDate(1L, "2010-01-01"),
-      DbCleanerTestUtils.createSnapshotWithDate(2L, "2010-12-25"),
-      DbCleanerTestUtils.createSnapshotWithDate(3L, "2012-01-01")
-      ));
-
-    assertThat(toDelete).onProperty("snapshotId").containsOnly(1L, 2L);
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/IntervalTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/IntervalTest.java
deleted file mode 100644 (file)
index 5a519f7..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.plugins.dbcleaner.period;
-
-import org.junit.Test;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.List;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.sonar.plugins.dbcleaner.DbCleanerTestUtils.createSnapshotWithDate;
-import static org.sonar.plugins.dbcleaner.DbCleanerTestUtils.createSnapshotWithDateTime;
-
-public class IntervalTest {
-  @Test
-  public void shouldGroupByIntervals() {
-    List<PurgeableSnapshotDto> snapshots = Arrays.asList(
-      createSnapshotWithDate(1L, "2011-04-03"),
-
-      createSnapshotWithDate(2L, "2011-05-01"),
-      createSnapshotWithDate(3L, "2011-05-19"),
-
-      createSnapshotWithDate(4L, "2011-06-02"),
-      createSnapshotWithDate(5L, "2011-06-20"),
-
-      createSnapshotWithDate(6L, "2012-06-29") // out of scope
-    );
-
-    List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2010-01-01"), DateUtils.parseDate("2011-12-31"), Calendar.MONTH);
-    assertThat(intervals.size(), is(3));
-
-    assertThat(intervals.get(0).count(), is(1));
-    assertThat(calendarField(intervals.get(0), Calendar.MONTH), is(Calendar.APRIL));
-
-    assertThat(intervals.get(1).count(), is(2));
-    assertThat(calendarField(intervals.get(1), Calendar.MONTH), is(Calendar.MAY));
-
-    assertThat(intervals.get(2).count(), is(2));
-    assertThat(calendarField(intervals.get(2), Calendar.MONTH), is(Calendar.JUNE));
-  }
-
-  @Test
-  public void shouldNotJoinMonthsOfDifferentYears() {
-    List<PurgeableSnapshotDto> snapshots = Arrays.asList(
-      createSnapshotWithDate(1L, "2010-04-03"),
-      createSnapshotWithDate(2L, "2011-04-13")
-    );
-
-    List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2010-01-01"), DateUtils.parseDate("2011-12-31"), Calendar.MONTH);
-    assertThat(intervals.size(), is(2));
-
-    assertThat(intervals.get(0).count(), is(1));
-    assertThat(calendarField(intervals.get(0), Calendar.MONTH), is(Calendar.APRIL));
-    assertThat(calendarField(intervals.get(0), Calendar.YEAR), is(2010));
-
-    assertThat(intervals.get(1).count(), is(1));
-    assertThat(calendarField(intervals.get(1), Calendar.MONTH), is(Calendar.APRIL));
-    assertThat(calendarField(intervals.get(1), Calendar.YEAR), is(2011));
-  }
-
-  @Test
-  public void shouldIgnoreTimeWhenGroupingByIntervals() {
-    List<PurgeableSnapshotDto> snapshots = Arrays.asList(
-      createSnapshotWithDateTime(1L, "2011-05-25T16:16:48+0100"),
-      createSnapshotWithDateTime(2L, "2012-01-26T16:16:48+0100"),
-      createSnapshotWithDateTime(3L, "2012-01-27T16:16:48+0100")
-    );
-
-    List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2011-05-25"), DateUtils.parseDate("2012-01-26"), Calendar.MONTH);
-    assertThat(intervals.size(), is(1));
-    assertThat(intervals.get(0).count(), is(1));
-    assertThat(intervals.get(0).get().get(0).getSnapshotId(), is(2L));
-  }
-
-  static int calendarField(Interval interval, int field) {
-    if (interval.count() == 0) {
-      return -1;
-    }
-
-    PurgeableSnapshotDto first = interval.get().iterator().next();
-    GregorianCalendar cal = new GregorianCalendar();
-    cal.setTime(first.getDate());
-    return cal.get(field);
-  }
-}
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneFilterTest.java b/plugins/sonar-dbcleaner-plugin/src/test/java/org/sonar/plugins/dbcleaner/period/KeepOneFilterTest.java
deleted file mode 100644 (file)
index 4a9ecd4..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.plugins.dbcleaner.period;
-
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-import org.junit.Test;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.core.purge.PurgeableSnapshotDto;
-
-import javax.annotation.Nullable;
-
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.List;
-
-import static com.google.common.collect.Lists.newArrayList;
-import static org.fest.assertions.Assertions.assertThat;
-import static org.sonar.plugins.dbcleaner.DbCleanerTestUtils.createSnapshotWithDate;
-
-public class KeepOneFilterTest {
-
-  @Test
-  public void shouldOnlyOneSnapshotPerInterval() {
-    Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month");
-
-    List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList(
-      createSnapshotWithDate(1L, "2010-01-01"), // out of scope -> keep
-      createSnapshotWithDate(2L, "2011-05-01"), // may -> keep
-      createSnapshotWithDate(3L, "2011-05-02"), // may -> to be deleted
-      createSnapshotWithDate(4L, "2011-05-19"), // may -> to be deleted
-      createSnapshotWithDate(5L, "2011-06-01"), // june -> keep
-      createSnapshotWithDate(6L, "2012-01-01") // out of scope -> keep
-      ));
-
-    assertThat(toDelete).hasSize(2);
-
-    List<Long> snapshotIds = snapshotIds(toDelete);
-    assertThat(snapshotIds).contains(3L);
-    assertThat(snapshotIds.contains(4L));
-  }
-
-  @Test
-  public void shouldKeepNonDeletableSnapshots() {
-    Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month");
-
-    List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList(
-      createSnapshotWithDate(1L, "2011-05-01"), // to be deleted
-      createSnapshotWithDate(2L, "2011-05-02").setLast(true),
-      createSnapshotWithDate(3L, "2011-05-19").setHasEvents(true).setLast(false),
-      createSnapshotWithDate(4L, "2011-05-23") // to be deleted
-      ));
-
-    assertThat(toDelete).hasSize(2);
-
-    List<Long> snapshotIds = snapshotIds(toDelete);
-    assertThat(snapshotIds).contains(1L);
-    assertThat(snapshotIds.contains(4L));
-  }
-
-  @Test
-  public void test_isDeletable() {
-    assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01"))).isTrue();
-    assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setLast(true))).isFalse();
-    assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setHasEvents(true))).isFalse();
-  }
-
-  private static List<Long> snapshotIds(List<PurgeableSnapshotDto> snapshotDtos){
-    return newArrayList(Iterables.transform(snapshotDtos, new Function<PurgeableSnapshotDto, Long>() {
-      @Override
-      public Long apply(@Nullable PurgeableSnapshotDto input) {
-        return input != null ? input.getSnapshotId() : null;
-      }
-    }));
-  }
-
-}
index 06a721129dbceab135c03ed720c0aec7a02e2307..2f2f78a39ee8507733cbf30cf880b6845a5aec22 100644 (file)
@@ -69,7 +69,6 @@ public class AnalysisReportQueue implements ServerComponent {
   private AnalysisReportDto newPendingAnalysisReport(String projectKey) {
     return new AnalysisReportDto()
       .setProjectKey(projectKey)
-      .setProjectName(projectKey)
       .setStatus(PENDING);
   }
 
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/AnalysisReportStep.java
deleted file mode 100644 (file)
index 2408bf3..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.computation;
-
-import org.sonar.api.ServerComponent;
-import org.sonar.core.computation.db.AnalysisReportDto;
-import org.sonar.core.persistence.DbSession;
-
-public interface AnalysisReportStep extends ServerComponent {
-  void execute(DbSession session, AnalysisReportDto analysisReportDto);
-}
index 642b5d9adb1052f8dae5d6e6273304c4bb8e4890..f2cf9c3f584d73e85b8c5cfed9bc3a46f4697016 100644 (file)
@@ -50,13 +50,7 @@ public class AnalysisReportTaskLauncher implements Startable, ServerComponent, S
   public AnalysisReportTaskLauncher(ComputationService service, AnalysisReportQueue queue) {
     this.service = service;
     this.queue = queue;
-
-    // all threads are named "ar-xxx", so they can have a dedicated logging output
-    // (see SwitchLogbackAppender)
-    ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
-      .setNameFormat(ANALYSIS_REPORT_THREAD_NAME_PREFIX + "%d").setPriority(Thread.MIN_PRIORITY).build();
-
-    this.executorService = Executors.newSingleThreadScheduledExecutor(namedThreadFactory);
+    this.executorService = Executors.newSingleThreadScheduledExecutor(threadFactoryWithSpecificNameForLogging());
 
     this.delayBetweenTasks = 10;
     this.delayForFirstStart = 0;
@@ -66,7 +60,7 @@ public class AnalysisReportTaskLauncher implements Startable, ServerComponent, S
   @VisibleForTesting
   AnalysisReportTaskLauncher(ComputationService service, AnalysisReportQueue queue, long delayForFirstStart, long delayBetweenTasks, TimeUnit timeUnit) {
     this.queue = queue;
-    this.executorService = Executors.newSingleThreadScheduledExecutor();
+    this.executorService = Executors.newSingleThreadScheduledExecutor(threadFactoryWithSpecificNameForLogging());
 
     this.delayBetweenTasks = delayBetweenTasks;
     this.delayForFirstStart = delayForFirstStart;
@@ -74,6 +68,14 @@ public class AnalysisReportTaskLauncher implements Startable, ServerComponent, S
     this.service = service;
   }
 
+  /**
+   * @see org.sonar.server.platform.SwitchLogbackAppender
+   */
+  private ThreadFactory threadFactoryWithSpecificNameForLogging() {
+    return new ThreadFactoryBuilder()
+      .setNameFormat(ANALYSIS_REPORT_THREAD_NAME_PREFIX + "%d").setPriority(Thread.MIN_PRIORITY).build();
+  }
+
   @Override
   public void start() {
     // do nothing because we want to wait for the server to finish startup
index e0dc2742290f909cddc3a41a28af9d071fc46951..f0cd88be1f0e787cbfe59f9d28ae8d52229f553b 100644 (file)
@@ -31,16 +31,11 @@ import org.sonar.server.db.DbClient;
  */
 public class ComputationService implements ServerComponent {
   private final DbClient dbClient;
-  private final SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep;
-  private final IndexProjectIssuesStep indexProjectIssuesStep;
-  private final SwitchSnapshotStep switchSnapshotStep;
+  private final ComputationStepRegistry stepRegistry;
 
-  public ComputationService(DbClient dbClient, SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep,
-    IndexProjectIssuesStep indexProjectIssuesStep, SwitchSnapshotStep switchSnapshotStep) {
+  public ComputationService(DbClient dbClient, ComputationStepRegistry stepRegistry) {
     this.dbClient = dbClient;
-    this.synchronizeProjectPermissionsStep = synchronizeProjectPermissionsStep;
-    this.indexProjectIssuesStep = indexProjectIssuesStep;
-    this.switchSnapshotStep = switchSnapshotStep;
+    this.stepRegistry = stepRegistry;
   }
 
   public void analyzeReport(AnalysisReportDto report) {
@@ -48,9 +43,9 @@ public class ComputationService implements ServerComponent {
     DbSession session = dbClient.openSession(true);
 
     try {
-      synchronizeProjectPermissionsStep.execute(session, report);
-      indexProjectIssuesStep.execute(session, report);
-      switchSnapshotStep.execute(session, report);
+      for (ComputationStep step : stepRegistry.steps()) {
+        step.execute(session, report);
+      }
     } finally {
       MyBatis.closeQuietly(session);
     }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationStep.java
new file mode 100644 (file)
index 0000000..d4cb50b
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.computation;
+
+import org.sonar.api.ServerComponent;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.persistence.DbSession;
+
+public interface ComputationStep extends ServerComponent {
+  void execute(DbSession session, AnalysisReportDto analysisReportDto);
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationStepRegistry.java b/server/sonar-server/src/main/java/org/sonar/server/computation/ComputationStepRegistry.java
new file mode 100644 (file)
index 0000000..c4f21a9
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.computation;
+
+import com.google.common.collect.ImmutableList;
+import org.sonar.api.ServerComponent;
+
+import java.util.List;
+
+public class ComputationStepRegistry implements ServerComponent {
+
+  private final List<ComputationStep> steps;
+
+  public ComputationStepRegistry(
+    GetAndSetProjectStep getAndSetProjectStep,
+    SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep,
+    IndexProjectIssuesStep indexProjectIssuesStep,
+    SwitchSnapshotStep switchSnapshotStep,
+    DbCleanerStep dbCleanerStep) {
+    steps = ImmutableList.of(getAndSetProjectStep, synchronizeProjectPermissionsStep, indexProjectIssuesStep, switchSnapshotStep, dbCleanerStep);
+  }
+
+  public List<ComputationStep> steps() {
+    return steps;
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/DbCleanerStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/DbCleanerStep.java
new file mode 100644 (file)
index 0000000..6556b5c
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.computation;
+
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.persistence.DbSession;
+
+public class DbCleanerStep implements ComputationStep {
+  private final DefaultPurgeTask purgeTask;
+
+  public DbCleanerStep(DefaultPurgeTask purgeTask) {
+    this.purgeTask = purgeTask;
+  }
+
+  @Override
+  public void execute(DbSession session, AnalysisReportDto report) {
+    purgeTask.purge(report.getProject().getId());
+  }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/GetAndSetProjectStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/GetAndSetProjectStep.java
new file mode 100644 (file)
index 0000000..7eb4091
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.computation;
+
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.db.DbClient;
+
+public class GetAndSetProjectStep implements ComputationStep {
+
+  private final DbClient dbClient;
+
+  public GetAndSetProjectStep(DbClient dbClient) {
+    this.dbClient = dbClient;
+  }
+
+  @Override
+  public void execute(DbSession session, AnalysisReportDto report) {
+    ComponentDto project = dbClient.componentDao().getByKey(session, report.getProjectKey());
+    report.setProject(project);
+  }
+}
index f49ad6c3fea7a43560a18335efd0352303a2bf43..96fa7abbf3b9c747fe69f7968d308da7dc975b77 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.server.db.DbClient;
 import org.sonar.server.issue.index.IssueIndex;
 import org.sonar.server.search.IndexClient;
 
-public class IndexProjectIssuesStep implements AnalysisReportStep {
+public class IndexProjectIssuesStep implements ComputationStep {
 
   private final DbClient dbClient;
   private final IndexClient index;
index 7e0f0a6e955b12d892647cf68b9298ef3d642012..368aeeed36292b138b0fb856a16cbd0e7d03ee6c 100644 (file)
@@ -27,7 +27,7 @@ import org.sonar.server.component.db.SnapshotDao;
 
 import java.util.List;
 
-public class SwitchSnapshotStep implements AnalysisReportStep {
+public class SwitchSnapshotStep implements ComputationStep {
 
   private SnapshotDao dao;
 
index 65efcd21924d9a61db8d4fe7eea523f720640b57..14f0b44cf33a13fb72455caf0d7c16c768179a74 100644 (file)
 
 package org.sonar.server.computation;
 
-import org.sonar.core.component.AuthorizedComponentDto;
 import org.sonar.core.computation.db.AnalysisReportDto;
 import org.sonar.core.persistence.DbSession;
-import org.sonar.server.db.DbClient;
 import org.sonar.server.issue.index.IssueAuthorizationIndex;
 import org.sonar.server.permission.InternalPermissionService;
 import org.sonar.server.search.IndexClient;
 
-public class SynchronizeProjectPermissionsStep implements AnalysisReportStep {
+public class SynchronizeProjectPermissionsStep implements ComputationStep {
 
   private final IndexClient index;
-  private final DbClient dbClient;
   private final InternalPermissionService permissionService;
 
-  public SynchronizeProjectPermissionsStep(IndexClient index, DbClient dbClient, InternalPermissionService permissionService) {
+  public SynchronizeProjectPermissionsStep(IndexClient index, InternalPermissionService permissionService) {
     this.index = index;
-    this.dbClient = dbClient;
     this.permissionService = permissionService;
   }
 
   @Override
   public void execute(DbSession session, AnalysisReportDto report) {
-    synchronizeProjectPermissionsIfNotFound(session, report.getProjectKey());
+    synchronizeProjectPermissionsIfNotFound(session, report);
   }
 
-  private void synchronizeProjectPermissionsIfNotFound(DbSession session, String projectKey) {
-    if (index.get(IssueAuthorizationIndex.class).getNullableByKey(projectKey) == null) {
-      // TODO Remove this db call by inserting the project uuid in the report
-      AuthorizedComponentDto project = dbClient.componentDao().getAuthorizedComponentByKey(projectKey, session);
-      permissionService.synchronizePermissions(session, project.uuid());
+  private void synchronizeProjectPermissionsIfNotFound(DbSession session, AnalysisReportDto report) {
+    if (index.get(IssueAuthorizationIndex.class).getNullableByKey(report.getProjectKey()) == null) {
+      permissionService.synchronizePermissions(session, report.getProject().uuid());
       session.commit();
     }
   }
index dd8b3a9877d506419441cc1e87eb561187bc7bbd..0288b69d3bb1c865be5352046a5f7378d549b2d6 100644 (file)
@@ -37,6 +37,8 @@ import org.sonar.api.utils.System2;
 import org.sonar.api.utils.UriReader;
 import org.sonar.api.utils.internal.TempFolderCleaner;
 import org.sonar.core.component.SnapshotPerspectives;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
 import org.sonar.core.config.CorePropertyDefinitions;
 import org.sonar.core.config.Logback;
 import org.sonar.core.i18n.DefaultI18n;
@@ -271,7 +273,7 @@ class ServerComponents {
       ActivityNormalizer.class,
       ActivityIndex.class,
       ActivityDao.class
-      ));
+    ));
     components.addAll(CorePropertyDefinitions.all());
     components.addAll(DatabaseMigrations.CLASSES);
     components.addAll(DaoUtils.getDaoClasses());
@@ -304,7 +306,7 @@ class ServerComponents {
       // ws
       RestartHandler.class,
       SystemWs.class
-      );
+    );
   }
 
   /**
@@ -321,7 +323,7 @@ class ServerComponents {
       HttpDownloader.class,
       UriReader.class,
       ServerIdGenerator.class
-      );
+    );
   }
 
   void startLevel4Components(ComponentContainer pico) {
@@ -591,15 +593,20 @@ class ServerComponents {
 
     // Compute engine
     pico.addSingleton(ComputationService.class);
-    pico.addSingleton(SwitchSnapshotStep.class);
+    pico.addSingleton(ComputationStepRegistry.class);
+    pico.addSingleton(GetAndSetProjectStep.class);
     pico.addSingleton(SynchronizeProjectPermissionsStep.class);
     pico.addSingleton(IndexProjectIssuesStep.class);
+    pico.addSingleton(SwitchSnapshotStep.class);
+    pico.addSingleton(DbCleanerStep.class);
     pico.add(AnalysisReportQueue.class);
     pico.addSingleton(AnalysisReportTaskLauncher.class);
     pico.addSingleton(AnalysisReportWebService.class);
     pico.addSingleton(ActiveAnalysisReportsAction.class);
     pico.addSingleton(IsAnalysisReportQueueEmptyAction.class);
     pico.addSingleton(AnalysisReportHistorySearchAction.class);
+    pico.addSingleton(DefaultPurgeTask.class);
+    pico.addSingleton(DefaultPeriodCleaner.class);
 
     for (Object components : level4AddedComponents) {
       pico.addSingleton(components);
index 0e4f2363a8ce87b0bace1053a7ecd4532f54039d..bf98168e8b281d5adf3c168d14f14d7c6dee4859 100644 (file)
@@ -31,6 +31,7 @@ import org.sonar.core.computation.db.AnalysisReportDto;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.server.activity.ActivityService;
 import org.sonar.server.activity.index.ActivityIndex;
+import org.sonar.server.component.ComponentTesting;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.tester.ServerTester;
 
@@ -65,12 +66,12 @@ public class AnalysisReportLogMediumTest {
   public void insert_find_analysis_report_log() {
     AnalysisReportDto report = AnalysisReportDto.newForTests(1L)
       .setProjectKey("projectKey")
-      .setProjectName("projectName")
       .setStatus(FAILED)
       .setCreatedAt(DateUtils.parseDate("2014-10-15"))
       .setUpdatedAt(DateUtils.parseDate("2014-10-16"))
       .setStartedAt(DateUtils.parseDate("2014-10-17"))
-      .setFinishedAt(DateUtils.parseDate("2014-10-18"));
+      .setFinishedAt(DateUtils.parseDate("2014-10-18"))
+      .setProject(ComponentTesting.newProjectDto());
 
     service.write(dbSession, ANALYSIS_REPORT, new AnalysisReportLog(report));
     dbSession.commit();
index 050330acba45728a2deef26c0003e13ea0a1f9d6..2e12107a20b579b3f12851294f3548c4df65043d 100644 (file)
@@ -35,6 +35,7 @@ import org.sonar.core.persistence.DbSession;
 import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.user.UserDto;
 import org.sonar.server.activity.index.ActivityIndex;
+import org.sonar.server.component.ComponentTesting;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.tester.ServerTester;
@@ -155,6 +156,7 @@ public class AnalysisReportQueueMediumTest {
     insertPermissionsForProject(DEFAULT_PROJECT_KEY);
     sut.add(DEFAULT_PROJECT_KEY, 123L);
     AnalysisReportDto report = sut.bookNextAvailable();
+    report.setProject(ComponentTesting.newProjectDto());
     report.setStatus(SUCCESS);
 
     sut.remove(report);
index 2910df149718ccfb57ab4992c1e8a373954d0097..9a99ec197fbd26dcb75bb5017d6ad93165dae190 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.sonar.server.computation;
 
+import com.google.common.collect.Lists;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.InOrder;
@@ -35,36 +36,30 @@ public class ComputationServiceTest {
   private ComputationService sut;
 
   private DbClient dbClient;
-  private IndexProjectIssuesStep indexProjectIssuesStep;
-  private SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep;
-  private SwitchSnapshotStep switchSnapshotStep;
+  private ComputationStepRegistry stepRegistry;
 
   @Before
   public void before() {
     this.dbClient = mock(DbClient.class);
+    this.stepRegistry = mock(ComputationStepRegistry.class);
 
-    this.indexProjectIssuesStep = mock(IndexProjectIssuesStep.class);
-    this.synchronizeProjectPermissionsStep = mock(SynchronizeProjectPermissionsStep.class);
-    this.switchSnapshotStep = mock(SwitchSnapshotStep.class);
-
-    this.sut = new ComputationService(dbClient, synchronizeProjectPermissionsStep, indexProjectIssuesStep, switchSnapshotStep);
+    this.sut = new ComputationService(dbClient, stepRegistry);
   }
 
   @Test
-  public void all_my_steps_are_called_in_the_right_order() {
-    sut.analyzeReport(AnalysisReportDto.newForTests(1L));
+  public void call_execute_method_of_my_registry() {
+    ComputationStep firstStep = mock(ComputationStep.class);
+    ComputationStep secondStep = mock(ComputationStep.class);
+    ComputationStep thirdStep = mock(ComputationStep.class);
 
-    InOrder inOrder = inOrder(indexProjectIssuesStep, synchronizeProjectPermissionsStep, switchSnapshotStep);
+    when(stepRegistry.steps()).thenReturn(Lists.newArrayList(firstStep, secondStep, thirdStep));
 
-    inOrder.verify(synchronizeProjectPermissionsStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
-    inOrder.verify(indexProjectIssuesStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
-    inOrder.verify(switchSnapshotStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
-  }
+    sut.analyzeReport(AnalysisReportDto.newForTests(1L));
 
-  @Test(expected = IllegalStateException.class)
-  public void computation_service_rethrows_exceptions() {
-    doThrow(IllegalStateException.class).when(switchSnapshotStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
+    InOrder order = inOrder(firstStep, secondStep, thirdStep);
 
-    sut.analyzeReport(AnalysisReportDto.newForTests(1L));
+    order.verify(firstStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
+    order.verify(secondStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
+    order.verify(thirdStep).execute(any(DbSession.class), any(AnalysisReportDto.class));
   }
 }
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationStepRegistryTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/ComputationStepRegistryTest.java
new file mode 100644 (file)
index 0000000..506db48
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.computation;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+public class ComputationStepRegistryTest {
+
+  private ComputationStepRegistry sut;
+  private GetAndSetProjectStep getAndSetProjectStep;
+  private SynchronizeProjectPermissionsStep synchronizeProjectPermissionsStep;
+  private IndexProjectIssuesStep indexProjectIssuesStep;
+  private SwitchSnapshotStep switchSnapshotStep;
+  private DbCleanerStep dbCleanerStep;
+
+  @Before
+  public void before() {
+    getAndSetProjectStep = mock(GetAndSetProjectStep.class);
+    synchronizeProjectPermissionsStep = mock(SynchronizeProjectPermissionsStep.class);
+    indexProjectIssuesStep = mock(IndexProjectIssuesStep.class);
+    switchSnapshotStep = mock(SwitchSnapshotStep.class);
+    dbCleanerStep = mock(DbCleanerStep.class);
+
+    sut = new ComputationStepRegistry(getAndSetProjectStep, synchronizeProjectPermissionsStep, indexProjectIssuesStep, switchSnapshotStep, dbCleanerStep);
+  }
+
+  @Test
+  public void steps_returned_in_the_right_order() throws Exception {
+    assertThat(sut.steps()).containsExactly(getAndSetProjectStep, synchronizeProjectPermissionsStep, indexProjectIssuesStep, switchSnapshotStep, dbCleanerStep);
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/DbCleanStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/DbCleanStepTest.java
new file mode 100644 (file)
index 0000000..8e09231
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.computation;
+
+import org.junit.Before;
+import org.sonar.api.config.Settings;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeProfiler;
+
+import static org.mockito.Mockito.mock;
+
+public class DbCleanStepTest {
+
+  private DbCleanerStep sut;
+
+  @Before
+  public void before() {
+    sut = new DbCleanerStep(new DefaultPurgeTask(mock(PurgeDao.class), mock(Settings.class), mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class)));
+  }
+
+}
\ No newline at end of file
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/DbCleanerStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/DbCleanerStepTest.java
new file mode 100644 (file)
index 0000000..ec6a437
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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.computation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.core.component.AuthorizedComponentDto;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.computation.dbcleaner.DefaultPurgeTask;
+import org.sonar.core.persistence.DbSession;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class DbCleanerStepTest {
+
+  private DbCleanerStep sut;
+  private DefaultPurgeTask purgeTask;
+
+  @Before
+  public void before() {
+    this.purgeTask = mock(DefaultPurgeTask.class);
+    this.sut = new DbCleanerStep(purgeTask);
+  }
+
+  @Test
+  public void call_purge_method_of_the_purge_task() {
+    AnalysisReportDto report = mock(AnalysisReportDto.class);
+    when(report.getProject()).thenReturn(mock(AuthorizedComponentDto.class));
+
+    sut.execute(mock(DbSession.class), report);
+
+    verify(purgeTask).purge(any(Long.class));
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/GetAndSetProjectStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/GetAndSetProjectStepTest.java
new file mode 100644 (file)
index 0000000..561559d
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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.computation;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.core.component.ComponentDto;
+import org.sonar.core.computation.db.AnalysisReportDto;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.server.component.ComponentTesting;
+import org.sonar.server.component.db.ComponentDao;
+import org.sonar.server.db.DbClient;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class GetAndSetProjectStepTest {
+
+  private GetAndSetProjectStep sut;
+  private DbClient dbClient;
+  private ComponentDto project;
+  private DbSession session;
+
+  @Before
+  public void before() {
+    this.dbClient = mock(DbClient.class);
+    this.session = mock(DbSession.class);
+    this.project = ComponentTesting.newProjectDto();
+
+    ComponentDao componentDao = mock(ComponentDao.class);
+    when(dbClient.componentDao()).thenReturn(componentDao);
+    when(componentDao.getByKey(any(DbSession.class), anyString())).thenReturn(project);
+
+    this.sut = new GetAndSetProjectStep(dbClient);
+  }
+
+  @Test
+  public void set_project_return_by_dbclient() {
+    AnalysisReportDto report = new AnalysisReportDto().setProjectKey("123-456-789");
+
+    sut.execute(session, report);
+
+    assertThat(report.getProject()).isEqualTo(project);
+  }
+
+}
index 99edc5f88f9226371df0952e894bdcc377f577b1..c248b93e786719a04593eac55c13d57e791ef602 100644 (file)
@@ -53,6 +53,7 @@ public class SynchronizeProjectPermissionsStepMediumTest {
   private SynchronizeProjectPermissionsStep sut;
 
   private AnalysisReportQueue queue;
+  private GetAndSetProjectStep getAndSetProjectStep;
   private DbClient db;
   private DbSession session;
   private MockUserSession userSession;
@@ -63,6 +64,7 @@ public class SynchronizeProjectPermissionsStepMediumTest {
     db = tester.get(DbClient.class);
     session = db.openSession(false);
     queue = tester.get(AnalysisReportQueue.class);
+    getAndSetProjectStep = tester.get(GetAndSetProjectStep.class);
 
     sut = tester.get(SynchronizeProjectPermissionsStep.class);
 
@@ -88,6 +90,7 @@ public class SynchronizeProjectPermissionsStepMediumTest {
 
     queue.add(DEFAULT_PROJECT_KEY, 123L);
     List<AnalysisReportDto> reports = queue.findByProjectKey(DEFAULT_PROJECT_KEY);
+    getAndSetProjectStep.execute(session, reports.get(0));
 
     sut.execute(session, reports.get(0));
 
index 5aa270e5bfb4172d46f253f3918dca160fb793ca..0c78f41524c463ca7b669e7202676e45f2fd49cd 100644 (file)
@@ -59,8 +59,6 @@ public class AnalysisReportDaoTest {
     this.sut = new AnalysisReportDao(system2);
 
     when(system2.now()).thenReturn(DateUtils.parseDate("2014-09-26").getTime());
-
-    db.prepareDbUnit(getClass(), "empty.xml");
   }
 
   @After
@@ -70,9 +68,10 @@ public class AnalysisReportDaoTest {
 
   @Test
   public void insert_multiple_reports() {
+    db.prepareDbUnit(getClass(), "empty.xml");
+
     AnalysisReportDto report = new AnalysisReportDto()
       .setProjectKey(DEFAULT_PROJECT_KEY)
-      .setProjectName(DEFAULT_PROJECT_NAME)
       .setSnapshotId(DEFAULT_SNAPSHOT_ID)
       .setData("data-project")
       .setStatus(PENDING)
@@ -169,7 +168,6 @@ public class AnalysisReportDaoTest {
     AnalysisReportDto report = sut.getById(session, 1L);
 
     assertThat(report.getProjectKey()).isEqualTo(DEFAULT_PROJECT_KEY);
-    assertThat(report.getProjectName()).isEqualTo(DEFAULT_PROJECT_NAME);
     assertThat(report.getCreatedAt()).isEqualTo(DateUtils.parseDate("2014-09-24"));
     assertThat(report.getUpdatedAt()).isEqualTo(DateUtils.parseDate("2014-09-25"));
     assertThat(report.getStartedAt()).isEqualTo(DateUtils.parseDate("2014-09-26"));
index 56817de98847764c40dc3be5d34466fc1c9004b9..f817a19606536b3931c9bb1fa72b21b0594ed51c 100644 (file)
@@ -51,7 +51,6 @@ public class ActiveAnalysisReportsActionTest {
   public void list_active_reports() throws Exception {
     AnalysisReportDto report = AnalysisReportDto
       .newForTests(1L)
-      .setProjectName("Project Name")
       .setProjectKey("project-name")
       .setStatus(PENDING)
       .setData(null)
index cb5e9a70c3fb367df5998e0e3f64439147bf4073..235bdc82bf4b905d71525584c173d7549cd797d4 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
@@ -12,7 +11,6 @@
   <analysis_reports
       id="2"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
@@ -22,7 +20,6 @@
   <analysis_reports
       id="3"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
index 001dfb1cd18e70b4737d4c6141d3ee71974bf3a8..0ea21d7befe4ea2d1a832eefdcacd511dfedd1cd 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
@@ -12,7 +11,6 @@
   <analysis_reports
       id="2"
       project_key="987654321-123456789"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
index 189aa5a770c2fdc962e093338c81feeafeac55c6..28cd8bbe001f034eb11bd47985ba33308ce6b72c 100644 (file)
@@ -2,7 +2,7 @@
   <analysis_reports
       id="1"
       project_key="123456789-987654321"
-      project_name="default project name"
+      project_name="[null]"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
@@ -14,7 +14,7 @@
   <analysis_reports
       id="2"
       project_key="123456789-987654321"
-      project_name="default project name"
+      project_name="[null]"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
index fad68c874f35d0a96fe67b0bf7f176acf4bb544b..d0288e72615b58ee6d3e0b002a926938c63195bf 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
index 8dfd1864cd9fc794c907ef6435b3b46af1d9517a..93d6b5a633170cd8795db2f25dfe8ef74c95c848 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
@@ -12,7 +11,6 @@
   <analysis_reports
       id="2"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
index 122cffa4607c8ea86412d47a503b89e5f33d2ad6..5dd3839051eb1bf68311f469e3440be5b46add7a 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
@@ -12,7 +11,6 @@
   <analysis_reports
       id="2"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
index 423acd8cd6f26287f695066fdc68b2a6c3d6646c..574cd7317f77e037b7c491355ea4bb545ae71078 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
index 9e7dfcc8966675d4c278a43fe336d72913e84651..a0d357a7dbd0d99bfc69a6cfc3a2040234c9f680 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="111111111-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
@@ -12,7 +11,6 @@
   <analysis_reports
       id="2"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
@@ -23,7 +21,6 @@
   <analysis_reports
       id="3"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
index eb3156a8d6e1061f0b94613f600b9c36d22c807a..3a24ab33e3771fea3c7a8c3ccd6212e7cda794fc 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
@@ -12,7 +11,6 @@
   <analysis_reports
       id="2"
       project_key="987654321-123456789"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
@@ -22,7 +20,6 @@
   <analysis_reports
       id="3"
       project_key="987654321-123456789"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
index c5ebf921ae6ceccf96c012c00b0c960a2d8ebb01..d0e7d2a31d926ff16fca27c2e7577917f6eb19c2 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="111111111-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
@@ -12,7 +11,6 @@
   <analysis_reports
       id="2"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
@@ -22,7 +20,6 @@
   <analysis_reports
       id="3"
       project_key="333333333-123456789"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
index a5f42f4fbc3439925f4bb5c3b34cd5f739f32def..94ff919df315f66745f077b5bb79baa56e349eb4 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="111111111-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
@@ -12,7 +11,6 @@
   <analysis_reports
       id="2"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
@@ -22,7 +20,6 @@
   <analysis_reports
       id="3"
       project_key="333333333-123456789"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
index eb3156a8d6e1061f0b94613f600b9c36d22c807a..3a24ab33e3771fea3c7a8c3ccd6212e7cda794fc 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
@@ -12,7 +11,6 @@
   <analysis_reports
       id="2"
       project_key="987654321-123456789"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
@@ -22,7 +20,6 @@
   <analysis_reports
       id="3"
       project_key="987654321-123456789"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
index 4a32fbe8dd02d8231060afa2fcc7de4c7bdb3719..93c30ab664ffa3b0198da1e4a1c496541170167e 100644 (file)
@@ -2,7 +2,7 @@
   <analysis_reports
       id="1"
       project_key="123456789-987654321"
-      project_name="default project name"
+      project_name="[null]"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
@@ -14,7 +14,7 @@
   <analysis_reports
       id="2"
       project_key="123456789-987654321"
-      project_name="default project name"
+      project_name="[null]"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
@@ -26,7 +26,7 @@
   <analysis_reports
       id="3"
       project_key="123456789-987654321"
-      project_name="default project name"
+      project_name="[null]"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
index 71e67e7b91193a2656f7c7729731759dfa2cf29b..ea47c0bd16e76484f3bb02964e8e05c6e3af3ee8 100644 (file)
@@ -2,7 +2,6 @@
   <analysis_reports
       id="1"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
@@ -14,7 +13,6 @@
   <analysis_reports
       id="2"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="WORKING"
@@ -26,7 +24,6 @@
   <analysis_reports
       id="3"
       project_key="123456789-987654321"
-      project_name="default project name"
       snapshot_id="123"
       report_data="data-project"
       report_status="PENDING"
index e5bd54abf0a86fb5e3652ba3d137fcd29b04a57a..a82f67d3e30df34714d7afaec972ba38dfb07f0e 100644 (file)
@@ -3,7 +3,7 @@
     {
       "id": 1,
       "status": "PENDING",
-      "projectName": "Project Name",
+      "projectName": "project-name",
       "project": "project-name",
       "submittedAt": "2014-10-13T00:00:00+0200",
       "startedAt": "2014-10-13T00:00:00+0200",
index 82c4af9526decb1a004b8a6a5bfbfb8ee0115f58..1491a1ae19c6e08d1fd8c3b25c2888565ff9a5f4 100644 (file)
@@ -21,12 +21,16 @@ package org.sonar.core.computation.db;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+import org.sonar.core.component.AuthorizedComponentDto;
+import org.sonar.core.component.ComponentDto;
 import org.sonar.core.persistence.Dto;
 
 import javax.annotation.Nullable;
 
 import java.util.Date;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static org.sonar.core.computation.db.AnalysisReportDto.Status.FAILED;
 import static org.sonar.core.computation.db.AnalysisReportDto.Status.SUCCESS;
 
@@ -34,12 +38,12 @@ public class AnalysisReportDto extends Dto<String> {
 
   private Long id;
   private String projectKey;
-  private String projectName;
   private Status status;
   private String data;
   private Long snapshotId;
   private Date startedAt;
   private Date finishedAt;
+  private ComponentDto project;
 
   public AnalysisReportDto() {
     super();
@@ -102,7 +106,6 @@ public class AnalysisReportDto extends Dto<String> {
     return Objects.toStringHelper(this)
       .add("id", getId())
       .add("projectKey", getProjectKey())
-      .add("projectName", getProjectName())
       .add("status", getStatus())
       .add("createdAt", getCreatedAt())
       .add("startedAt", getStartedAt())
@@ -111,12 +114,11 @@ public class AnalysisReportDto extends Dto<String> {
   }
 
   public String getProjectName() {
-    return projectName;
-  }
+    if (project == null) {
+      return getProjectKey();
+    }
 
-  public AnalysisReportDto setProjectName(String projectName) {
-    this.projectName = projectName;
-    return this;
+    return Strings.nullToEmpty(project.name());
   }
 
   public Long getSnapshotId() {
@@ -158,6 +160,15 @@ public class AnalysisReportDto extends Dto<String> {
     return this;
   }
 
+  public AuthorizedComponentDto getProject() {
+    return checkNotNull(project);
+  }
+
+  public AnalysisReportDto setProject(ComponentDto project) {
+    this.project = project;
+    return this;
+  }
+
   public enum Status {
     PENDING, WORKING, SUCCESS, FAILED;
 
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DbCleanerConstants.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DbCleanerConstants.java
new file mode 100644 (file)
index 0000000..a577f63
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.core.computation.dbcleaner;
+
+public interface DbCleanerConstants {
+
+  String PLUGIN_KEY = "dbcleaner";
+  String PLUGIN_NAME = "DbCleaner";
+  String PROPERTY_CLEAN_DIRECTORY = "sonar.dbcleaner.cleanDirectory";
+
+  String HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY = "sonar.dbcleaner.hoursBeforeKeepingOnlyOneSnapshotByDay";
+  String WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK = "sonar.dbcleaner.weeksBeforeKeepingOnlyOneSnapshotByWeek";
+  String WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH = "sonar.dbcleaner.weeksBeforeKeepingOnlyOneSnapshotByMonth";
+  String WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS = "sonar.dbcleaner.weeksBeforeDeletingAllSnapshots";
+  String DAYS_BEFORE_DELETING_CLOSED_ISSUES = "sonar.dbcleaner.daysBeforeDeletingClosedIssues";
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DbCleanerProperties.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DbCleanerProperties.java
new file mode 100644 (file)
index 0000000..744a887
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * 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.core.computation.dbcleaner;
+
+import org.sonar.api.CoreProperties;
+import org.sonar.api.PropertyType;
+import org.sonar.api.config.PropertyDefinition;
+import org.sonar.api.resources.Qualifiers;
+
+import java.util.Arrays;
+import java.util.List;
+
+public final class DbCleanerProperties {
+
+  public static List<PropertyDefinition> all() {
+    return Arrays.asList(
+      PropertyDefinition.builder(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)
+        .defaultValue("true")
+        .name("Clean directory/package history")
+        .description("If set to true, no history is kept at directory/package level. Setting this to false can cause database bloat.")
+        .type(PropertyType.BOOLEAN)
+        .onQualifiers(Qualifiers.PROJECT)
+        .category(CoreProperties.CATEGORY_GENERAL)
+        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+        .index(1)
+        .build(),
+
+      PropertyDefinition.builder(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES)
+        .defaultValue("30")
+        .name("Delete closed issues after")
+        .description("Issues that have been closed for more than this number of days will be deleted.")
+        .type(PropertyType.INTEGER)
+        .onQualifiers(Qualifiers.PROJECT)
+        .category(CoreProperties.CATEGORY_GENERAL)
+        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+        .index(2)
+        .build(),
+
+      PropertyDefinition.builder(DbCleanerConstants.HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY)
+        .defaultValue("24")
+        .name("Keep only one snapshot a day after")
+        .description("After this number of hours, if there are several snapshots during the same day, "
+          + "the DbCleaner keeps the most recent one and fully deletes the other ones.")
+        .type(PropertyType.INTEGER)
+        .onQualifiers(Qualifiers.PROJECT)
+        .category(CoreProperties.CATEGORY_GENERAL)
+        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+        .index(3)
+        .build(),
+
+      PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK)
+        .defaultValue("4")
+        .name("Keep only one snapshot a week after")
+        .description("After this number of weeks, if there are several snapshots during the same week, "
+          + "the DbCleaner keeps the most recent one and fully deletes the other ones")
+        .type(PropertyType.INTEGER)
+        .onQualifiers(Qualifiers.PROJECT)
+        .category(CoreProperties.CATEGORY_GENERAL)
+        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+        .index(4)
+        .build(),
+
+      PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH)
+        .defaultValue("52")
+        .name("Keep only one snapshot a month after")
+        .description("After this number of weeks, if there are several snapshots during the same month, "
+          + "the DbCleaner keeps the most recent one and fully deletes the other ones.")
+        .type(PropertyType.INTEGER)
+        .onQualifiers(Qualifiers.PROJECT)
+        .category(CoreProperties.CATEGORY_GENERAL)
+        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+        .index(5)
+        .build(),
+
+      PropertyDefinition.builder(DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS)
+        .defaultValue("260")
+        .name("Delete all snapshots after")
+        .description("After this number of weeks, all snapshots are fully deleted.")
+        .type(PropertyType.INTEGER)
+        .onQualifiers(Qualifiers.PROJECT)
+        .category(CoreProperties.CATEGORY_GENERAL)
+        .subCategory(CoreProperties.SUBCATEGORY_DATABASE_CLEANER)
+        .index(6)
+        .build()
+    );
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java
new file mode 100644 (file)
index 0000000..4cd7799
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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.core.computation.dbcleaner;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Scopes;
+import org.sonar.api.utils.TimeUtils;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.purge.PurgeConfiguration;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeProfiler;
+
+/**
+ * @since 2.14
+ */
+public class DefaultPurgeTask {
+  private static final Logger LOG = LoggerFactory.getLogger(DefaultPurgeTask.class);
+
+  private PurgeDao purgeDao;
+  private Settings settings;
+  private DefaultPeriodCleaner periodCleaner;
+  private final PurgeProfiler profiler;
+
+  public DefaultPurgeTask(PurgeDao purgeDao, Settings settings, DefaultPeriodCleaner periodCleaner, PurgeProfiler profiler) {
+    this.purgeDao = purgeDao;
+    this.settings = settings;
+    this.periodCleaner = periodCleaner;
+    this.profiler = profiler;
+  }
+
+  public DefaultPurgeTask delete(long resourceId) {
+    purgeDao.deleteResourceTree(resourceId);
+    return this;
+  }
+
+  public DefaultPurgeTask purge(long resourceId) {
+    long start = System.currentTimeMillis();
+    profiler.reset();
+    cleanHistoricalData(resourceId);
+    doPurge(resourceId);
+    if (settings.getBoolean(CoreProperties.PROFILING_LOG_PROPERTY)) {
+      long duration = System.currentTimeMillis() - start;
+      LOG.info("\n -------- Profiling for purge: " + TimeUtils.formatDuration(duration) + " --------\n");
+      profiler.dump(duration, LOG);
+      LOG.info("\n -------- End of profiling for purge --------\n");
+    }
+    return this;
+  }
+
+  private void cleanHistoricalData(long resourceId) {
+    try {
+      periodCleaner.clean(resourceId);
+    } catch (Exception e) {
+      // purge errors must no fail the batch
+      LOG.error("Fail to clean historical data [id=" + resourceId + "]", e);
+    }
+  }
+
+  private void doPurge(long resourceId) {
+    try {
+      purgeDao.purge(newConf(resourceId));
+    } catch (Exception e) {
+      // purge errors must no fail the batch
+      LOG.error("Fail to purge data [id=" + resourceId + "]", e);
+    }
+  }
+
+  private PurgeConfiguration newConf(long resourceId) {
+    String[] scopes = new String[] {Scopes.FILE};
+    if (settings.getBoolean(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY)) {
+      scopes = new String[] {Scopes.DIRECTORY, Scopes.FILE};
+    }
+    return new PurgeConfiguration(resourceId, scopes, settings.getInt(DbCleanerConstants.DAYS_BEFORE_DELETING_CLOSED_ISSUES));
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleaner.java
new file mode 100644 (file)
index 0000000..76b1238
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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.core.computation.dbcleaner.period;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Project;
+import org.sonar.api.task.TaskExtension;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeSnapshotQuery;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.List;
+
+public class DefaultPeriodCleaner implements TaskExtension {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DefaultPeriodCleaner.class);
+  private PurgeDao purgeDao;
+  private Settings settings;
+
+  public DefaultPeriodCleaner(PurgeDao purgeDao, Settings settings) {
+    this.purgeDao = purgeDao;
+    this.settings = settings;
+  }
+
+  public void purge(Project project, int projectSnapshotId) {
+    clean(project.getId());
+  }
+
+  public void clean(long projectId) {
+    doClean(projectId, new Filters(settings).all());
+  }
+
+  @VisibleForTesting
+  void doClean(long projectId, List<Filter> filters) {
+    List<PurgeableSnapshotDto> history = selectProjectSnapshots(projectId);
+    for (Filter filter : filters) {
+      filter.log();
+      delete(filter.filter(history));
+    }
+  }
+
+  private void delete(List<PurgeableSnapshotDto> snapshots) {
+    for (PurgeableSnapshotDto snapshot : snapshots) {
+      LOG.info("<- Delete snapshot: " + DateUtils.formatDateTime(snapshot.getDate()) + " [" + snapshot.getSnapshotId() + "]");
+      purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setRootSnapshotId(snapshot.getSnapshotId()));
+      purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setId(snapshot.getSnapshotId()));
+    }
+  }
+
+  private List<PurgeableSnapshotDto> selectProjectSnapshots(long resourceId) {
+    return purgeDao.selectPurgeableSnapshots(resourceId);
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DeleteAllFilter.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/DeleteAllFilter.java
new file mode 100644 (file)
index 0000000..25dcb40
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.core.computation.dbcleaner.period;
+
+import com.google.common.collect.Lists;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Date;
+import java.util.List;
+
+class DeleteAllFilter implements Filter {
+  private final Date before;
+
+  public DeleteAllFilter(Date before) {
+    this.before = before;
+  }
+
+  @Override
+  public List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) {
+    List<PurgeableSnapshotDto> result = Lists.newArrayList();
+    for (PurgeableSnapshotDto snapshot : history) {
+      if (snapshot.getDate().before(before)) {
+        result.add(snapshot);
+      }
+    }
+    return result;
+  }
+
+  @Override
+  public void log() {
+    LoggerFactory.getLogger(getClass()).info("-> Delete data prior to: " + DateUtils.formatDate(before));
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/Filter.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/Filter.java
new file mode 100644 (file)
index 0000000..ef4a375
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.core.computation.dbcleaner.period;
+
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.List;
+
+interface Filter {
+  List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> snapshots);
+
+  void log();
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/Filters.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/Filters.java
new file mode 100644 (file)
index 0000000..8e59596
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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.core.computation.dbcleaner.period;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.time.DateUtils;
+import org.sonar.api.config.Settings;
+import org.sonar.core.computation.dbcleaner.DbCleanerConstants;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+class Filters {
+  private final List<Filter> all = Lists.newArrayList();
+
+  Filters(Settings settings) {
+    Date dateToStartKeepingOneSnapshotByDay = getDateFromHours(settings, DbCleanerConstants.HOURS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_DAY);
+    Date dateToStartKeepingOneSnapshotByWeek = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_WEEK);
+    Date dateToStartKeepingOneSnapshotByMonth = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_KEEPING_ONLY_ONE_SNAPSHOT_BY_MONTH);
+    Date dateToStartDeletingAllSnapshots = getDateFromWeeks(settings, DbCleanerConstants.WEEKS_BEFORE_DELETING_ALL_SNAPSHOTS);
+
+    all.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByWeek, dateToStartKeepingOneSnapshotByDay, Calendar.DAY_OF_YEAR, "day"));
+    all.add(new KeepOneFilter(dateToStartKeepingOneSnapshotByMonth, dateToStartKeepingOneSnapshotByWeek, Calendar.WEEK_OF_YEAR, "week"));
+    all.add(new KeepOneFilter(dateToStartDeletingAllSnapshots, dateToStartKeepingOneSnapshotByMonth, Calendar.MONTH, "month"));
+    all.add(new DeleteAllFilter(dateToStartDeletingAllSnapshots));
+  }
+
+  static Date getDateFromWeeks(Settings settings, String propertyKey) {
+    int weeks = settings.getInt(propertyKey);
+    return DateUtils.addWeeks(new Date(), -weeks);
+  }
+
+  static Date getDateFromHours(Settings settings, String propertyKey) {
+    int hours = settings.getInt(propertyKey);
+    return DateUtils.addHours(new Date(), -hours);
+  }
+
+  List<Filter> all() {
+    return all;
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/Interval.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/Interval.java
new file mode 100644 (file)
index 0000000..5676a85
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.core.computation.dbcleaner.period;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.time.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+final class Interval {
+  List<PurgeableSnapshotDto> snapshots = Lists.newArrayList();
+
+  void add(PurgeableSnapshotDto snapshot) {
+    snapshots.add(snapshot);
+  }
+
+  List<PurgeableSnapshotDto> get() {
+    return snapshots;
+  }
+
+  int count() {
+    return snapshots.size();
+  }
+
+  static List<Interval> group(List<PurgeableSnapshotDto> snapshots, Date start, Date end, int calendarField) {
+    List<Interval> intervals = Lists.newArrayList();
+
+    GregorianCalendar calendar = new GregorianCalendar();
+    int lastYear = -1;
+    int lastFieldValue = -1;
+    Interval currentInterval = null;
+
+    for (PurgeableSnapshotDto snapshot : snapshots) {
+      if (!DateUtils.isSameDay(start, snapshot.getDate()) && snapshot.getDate().after(start) &&
+        (snapshot.getDate().before(end) || DateUtils.isSameDay(end, snapshot.getDate()))) {
+        calendar.setTime(snapshot.getDate());
+        int currentFieldValue = calendar.get(calendarField);
+        int currentYear = calendar.get(Calendar.YEAR);
+        if (lastYear!=currentYear || lastFieldValue != currentFieldValue) {
+          currentInterval = new Interval();
+          intervals.add(currentInterval);
+        }
+        lastFieldValue = currentFieldValue;
+        lastYear = currentYear;
+        if (currentInterval != null) {
+          currentInterval.add(snapshot);
+        }
+      }
+    }
+    return intervals;
+  }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/KeepOneFilter.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/KeepOneFilter.java
new file mode 100644 (file)
index 0000000..419add8
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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.core.computation.dbcleaner.period;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.Lists;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Date;
+import java.util.List;
+
+class KeepOneFilter implements Filter {
+
+  private final Date start;
+  private final Date end;
+  private final int dateField;
+  private final String label;
+
+  KeepOneFilter(Date start, Date end, int calendarField, String label) {
+    this.start = start;
+    this.end = end;
+    this.dateField = calendarField;
+    this.label = label;
+  }
+
+  @Override
+  public List<PurgeableSnapshotDto> filter(List<PurgeableSnapshotDto> history) {
+    List<Interval> intervals = Interval.group(history, start, end, dateField);
+    List<PurgeableSnapshotDto> result = Lists.newArrayList();
+    for (Interval interval : intervals) {
+      appendSnapshotsToDelete(interval, result);
+    }
+
+    return result;
+  }
+
+  @Override
+  public void log() {
+    LoggerFactory.getLogger(getClass()).info("-> Keep one snapshot per " + label + " between " + DateUtils.formatDate(start) + " and " + DateUtils.formatDate(end));
+  }
+
+  private void appendSnapshotsToDelete(Interval interval, List<PurgeableSnapshotDto> toDelete) {
+    if (interval.count() > 1) {
+      List<PurgeableSnapshotDto> deletables = Lists.newArrayList();
+      List<PurgeableSnapshotDto> toKeep = Lists.newArrayList();
+      for (PurgeableSnapshotDto snapshot : interval.get()) {
+        if (isDeletable(snapshot)) {
+          deletables.add(snapshot);
+        } else {
+          toKeep.add(snapshot);
+        }
+      }
+
+      if (!toKeep.isEmpty()) {
+        toDelete.addAll(deletables);
+
+      } else if (deletables.size() > 1) {
+        // keep one snapshot
+        toDelete.addAll(deletables.subList(1, deletables.size()));
+      }
+    }
+  }
+
+  @VisibleForTesting
+  static boolean isDeletable(PurgeableSnapshotDto snapshot) {
+    return !snapshot.isLast() && !snapshot.hasEvents();
+  }
+
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/package-info.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/period/package-info.java
new file mode 100644 (file)
index 0000000..283ef7f
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.core.computation.dbcleaner.period;
+
+import javax.annotation.ParametersAreNonnullByDefault;
index d98fddab931190d4b76168056106d59ef44364ce..b678394d38a5b1912012b8a9d17e26202620e89b 100644 (file)
@@ -24,6 +24,7 @@ import com.google.common.collect.Lists;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.config.PropertyDefinition;
 import org.sonar.api.resources.Qualifiers;
+import org.sonar.core.computation.dbcleaner.DbCleanerProperties;
 
 import java.util.List;
 
@@ -39,6 +40,7 @@ public class CorePropertyDefinitions {
     defs.addAll(ExclusionProperties.all());
     defs.addAll(SecurityProperties.all());
     defs.addAll(DebtProperties.all());
+    defs.addAll(DbCleanerProperties.all());
 
     defs.addAll(ImmutableList.of(
       // BATCH
@@ -101,7 +103,7 @@ public class CorePropertyDefinitions {
         .category(CoreProperties.CATEGORY_GENERAL)
         .subCategory(CoreProperties.SUBCATEGORY_DIFFERENTIAL_VIEWS)
         .build()
-      ));
+    ));
     return defs;
   }
 }
index e2166b7b36fb9a3738703cbd54b6165aa243bd68..16613e4a946c60629df99c7588bbb89688a384b2 100644 (file)
@@ -6,7 +6,6 @@
     <!-- the data report is not brought back by default as it could be too big in memory -->
     ar.id,
     ar.project_key as projectKey,
-    ar.project_name as projectName,
     ar.report_status as status,
     ar.snapshot_id as snapshotId,
     ar.created_at as createdAt,
@@ -17,9 +16,9 @@
 
   <insert id="insert" parameterType="AnalysisReport" useGeneratedKeys="true">
     insert into analysis_reports
-    (project_key, project_name, snapshot_id, report_status, report_data, created_at, updated_at, started_at,
+    (project_key, snapshot_id, report_status, report_data, created_at, updated_at, started_at,
     finished_at)
-    values (#{projectKey}, #{projectName}, #{snapshotId}, #{status}, #{data}, #{createdAt}, #{updatedAt}, #{startedAt},
+    values (#{projectKey}, #{snapshotId}, #{status}, #{data}, #{createdAt}, #{updatedAt}, #{startedAt},
     #{finishedAt})
   </insert>
 
diff --git a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DbCleanerPropertiesTest.java b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DbCleanerPropertiesTest.java
new file mode 100644 (file)
index 0000000..4c4311a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.core.computation.dbcleaner;
+
+import org.junit.Test;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DbCleanerPropertiesTest {
+
+  @Test
+  public void shouldGetExtensions() {
+    assertThat(new DbCleanerProperties().all()).hasSize(6);
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DbCleanerTestUtils.java b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DbCleanerTestUtils.java
new file mode 100644 (file)
index 0000000..392e58c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.core.computation.dbcleaner;
+
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+public final class DbCleanerTestUtils {
+
+  private DbCleanerTestUtils() {
+  }
+
+  public static PurgeableSnapshotDto createSnapshotWithDate(long snapshotId, String date) {
+    PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto();
+    snapshot.setSnapshotId(snapshotId);
+    snapshot.setDate(DateUtils.parseDate(date));
+    return snapshot;
+  }
+
+  public static PurgeableSnapshotDto createSnapshotWithDateTime(long snapshotId, String datetime) {
+    PurgeableSnapshotDto snapshot = new PurgeableSnapshotDto();
+    snapshot.setSnapshotId(snapshotId);
+    snapshot.setDate(DateUtils.parseDateTime(datetime));
+    return snapshot;
+  }
+
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java
new file mode 100644 (file)
index 0000000..72359ee
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * 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.core.computation.dbcleaner;
+
+import ch.qos.logback.classic.Logger;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Scopes;
+import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.purge.PurgeConfiguration;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeProfiler;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.*;
+
+public class DefaultPurgeTaskTest {
+
+  @Test
+  public void shouldNotDeleteHistoricalDataOfDirectories() {
+    PurgeDao purgeDao = mock(PurgeDao.class);
+    Settings settings = new Settings(new PropertyDefinitions(DbCleanerProperties.all()));
+    settings.setProperty(DbCleanerConstants.PROPERTY_CLEAN_DIRECTORY, "false");
+    DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
+
+    task.purge(1L);
+
+    verify(purgeDao).purge(argThat(new ArgumentMatcher<PurgeConfiguration>() {
+      @Override
+      public boolean matches(Object o) {
+        PurgeConfiguration conf = (PurgeConfiguration) o;
+        return conf.rootProjectId() == 1L && conf.scopesWithoutHistoricalData().length == 1 && conf.scopesWithoutHistoricalData()[0].equals(Scopes.FILE);
+      }
+    }));
+  }
+
+  @Test
+  public void shouldDeleteHistoricalDataOfDirectoriesByDefault() {
+    PurgeDao purgeDao = mock(PurgeDao.class);
+    Settings settings = new Settings(new PropertyDefinitions(DbCleanerProperties.all()));
+    DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
+
+    task.purge(1L);
+
+    verify(purgeDao).purge(argThat(new ArgumentMatcher<PurgeConfiguration>() {
+      @Override
+      public boolean matches(Object o) {
+        PurgeConfiguration conf = (PurgeConfiguration) o;
+        return conf.rootProjectId() == 1L &&
+          conf.scopesWithoutHistoricalData().length == 2 &&
+          conf.scopesWithoutHistoricalData()[0].equals(Scopes.DIRECTORY) &&
+          conf.scopesWithoutHistoricalData()[1].equals(Scopes.FILE);
+      }
+    }));
+  }
+
+  @Test
+  public void shouldNotFailOnErrors() {
+    PurgeDao purgeDao = mock(PurgeDao.class);
+    when(purgeDao.purge(any(PurgeConfiguration.class))).thenThrow(new RuntimeException());
+    DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, new Settings(), mock(DefaultPeriodCleaner.class), mock(PurgeProfiler.class));
+
+    task.purge(1L);
+
+    verify(purgeDao, times(1)).purge(any(PurgeConfiguration.class));
+  }
+
+  @Test
+  public void shouldDumpProfiling() {
+    PurgeConfiguration conf = new PurgeConfiguration(1L, new String[0], 30);
+    PurgeDao purgeDao = mock(PurgeDao.class);
+    when(purgeDao.purge(conf)).thenThrow(new RuntimeException());
+    Settings settings = new Settings(new PropertyDefinitions(DbCleanerProperties.all()));
+    settings.setProperty(CoreProperties.PROFILING_LOG_PROPERTY, true);
+    PurgeProfiler profiler = mock(PurgeProfiler.class);
+
+    DefaultPurgeTask task = new DefaultPurgeTask(purgeDao, settings, mock(DefaultPeriodCleaner.class), profiler);
+    task.purge(1L);
+
+    verify(profiler).dump(anyLong(), any(Logger.class));
+  }
+
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleanerTest.java b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/DefaultPeriodCleanerTest.java
new file mode 100644 (file)
index 0000000..0a58720
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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.core.computation.dbcleaner.period;
+
+import org.apache.commons.lang.ObjectUtils;
+import org.hamcrest.BaseMatcher;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.sonar.api.config.Settings;
+import org.sonar.core.purge.PurgeDao;
+import org.sonar.core.purge.PurgeSnapshotQuery;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Arrays;
+import java.util.Date;
+
+import static org.mockito.Matchers.anyListOf;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.*;
+
+public class DefaultPeriodCleanerTest {
+
+
+  @Test
+  public void doClean() {
+    PurgeDao dao = mock(PurgeDao.class);
+    when(dao.selectPurgeableSnapshots(123L)).thenReturn(Arrays.asList(
+        new PurgeableSnapshotDto().setSnapshotId(999L).setDate(new Date())));
+    Filter filter1 = newLazyFilter();
+    Filter filter2 = newLazyFilter();
+
+    DefaultPeriodCleaner cleaner = new DefaultPeriodCleaner(dao, mock(Settings.class));
+    cleaner.doClean(123L, Arrays.asList(filter1, filter2));
+
+    verify(filter1).log();
+    verify(filter2).log();
+    verify(dao, times(2)).deleteSnapshots(argThat(newRootSnapshotQuery()));
+    verify(dao, times(2)).deleteSnapshots(argThat(newSnapshotIdQuery()));
+  }
+
+  private BaseMatcher<PurgeSnapshotQuery> newRootSnapshotQuery() {
+    return new ArgumentMatcher<PurgeSnapshotQuery>() {
+      @Override
+      public boolean matches(Object o) {
+        PurgeSnapshotQuery query = (PurgeSnapshotQuery) o;
+        return ObjectUtils.equals(query.getRootSnapshotId(), 999L);
+      }
+    };
+  }
+
+  private BaseMatcher<PurgeSnapshotQuery> newSnapshotIdQuery() {
+    return new ArgumentMatcher<PurgeSnapshotQuery>() {
+      @Override
+      public boolean matches(Object o) {
+        PurgeSnapshotQuery query = (PurgeSnapshotQuery) o;
+        return ObjectUtils.equals(query.getId(), 999L);
+      }
+    };
+  }
+
+  private Filter newLazyFilter() {
+    Filter filter1 = mock(Filter.class);
+    when(filter1.filter(anyListOf(PurgeableSnapshotDto.class))).thenAnswer(new Answer<Object>() {
+      public Object answer(InvocationOnMock invocation) throws Throwable {
+        return invocation.getArguments()[0];
+      }
+    });
+    return filter1;
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/DeleteAllFilterTest.java b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/DeleteAllFilterTest.java
new file mode 100644 (file)
index 0000000..2a84512
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.core.computation.dbcleaner.period;
+
+import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.computation.dbcleaner.DbCleanerTestUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class DeleteAllFilterTest {
+
+  @Test
+  public void shouldDeleteAllSnapshotsPriorToDate() {
+    Filter filter = new DeleteAllFilter(DateUtils.parseDate("2011-12-25"));
+
+    List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.asList(
+      DbCleanerTestUtils.createSnapshotWithDate(1L, "2010-01-01"),
+      DbCleanerTestUtils.createSnapshotWithDate(2L, "2010-12-25"),
+      DbCleanerTestUtils.createSnapshotWithDate(3L, "2012-01-01")
+      ));
+
+    assertThat(toDelete).onProperty("snapshotId").containsOnly(1L, 2L);
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/IntervalTest.java b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/IntervalTest.java
new file mode 100644 (file)
index 0000000..a9c5aec
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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.core.computation.dbcleaner.period;
+
+import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.sonar.core.computation.dbcleaner.DbCleanerTestUtils.createSnapshotWithDate;
+import static org.sonar.core.computation.dbcleaner.DbCleanerTestUtils.createSnapshotWithDateTime;
+
+public class IntervalTest {
+  static int calendarField(Interval interval, int field) {
+    if (interval.count() == 0) {
+      return -1;
+    }
+
+    PurgeableSnapshotDto first = interval.get().iterator().next();
+    GregorianCalendar cal = new GregorianCalendar();
+    cal.setTime(first.getDate());
+    return cal.get(field);
+  }
+
+  @Test
+  public void shouldGroupByIntervals() {
+    List<PurgeableSnapshotDto> snapshots = Arrays.asList(
+      createSnapshotWithDate(1L, "2011-04-03"),
+
+      createSnapshotWithDate(2L, "2011-05-01"),
+      createSnapshotWithDate(3L, "2011-05-19"),
+
+      createSnapshotWithDate(4L, "2011-06-02"),
+      createSnapshotWithDate(5L, "2011-06-20"),
+
+      createSnapshotWithDate(6L, "2012-06-29") // out of scope
+      );
+
+    List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2010-01-01"), DateUtils.parseDate("2011-12-31"), Calendar.MONTH);
+    assertThat(intervals.size(), is(3));
+
+    assertThat(intervals.get(0).count(), is(1));
+    assertThat(calendarField(intervals.get(0), Calendar.MONTH), is(Calendar.APRIL));
+
+    assertThat(intervals.get(1).count(), is(2));
+    assertThat(calendarField(intervals.get(1), Calendar.MONTH), is(Calendar.MAY));
+
+    assertThat(intervals.get(2).count(), is(2));
+    assertThat(calendarField(intervals.get(2), Calendar.MONTH), is(Calendar.JUNE));
+  }
+
+  @Test
+  public void shouldNotJoinMonthsOfDifferentYears() {
+    List<PurgeableSnapshotDto> snapshots = Arrays.asList(
+      createSnapshotWithDate(1L, "2010-04-03"),
+      createSnapshotWithDate(2L, "2011-04-13")
+      );
+
+    List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2010-01-01"), DateUtils.parseDate("2011-12-31"), Calendar.MONTH);
+    assertThat(intervals.size(), is(2));
+
+    assertThat(intervals.get(0).count(), is(1));
+    assertThat(calendarField(intervals.get(0), Calendar.MONTH), is(Calendar.APRIL));
+    assertThat(calendarField(intervals.get(0), Calendar.YEAR), is(2010));
+
+    assertThat(intervals.get(1).count(), is(1));
+    assertThat(calendarField(intervals.get(1), Calendar.MONTH), is(Calendar.APRIL));
+    assertThat(calendarField(intervals.get(1), Calendar.YEAR), is(2011));
+  }
+
+  @Test
+  public void shouldIgnoreTimeWhenGroupingByIntervals() {
+    List<PurgeableSnapshotDto> snapshots = Arrays.asList(
+      createSnapshotWithDateTime(1L, "2011-05-25T16:16:48+0100"),
+      createSnapshotWithDateTime(2L, "2012-01-26T16:16:48+0100"),
+      createSnapshotWithDateTime(3L, "2012-01-27T16:16:48+0100")
+      );
+
+    List<Interval> intervals = Interval.group(snapshots, DateUtils.parseDate("2011-05-25"), DateUtils.parseDate("2012-01-26"), Calendar.MONTH);
+    assertThat(intervals.size(), is(1));
+    assertThat(intervals.get(0).count(), is(1));
+    assertThat(intervals.get(0).get().get(0).getSnapshotId(), is(2L));
+  }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/KeepOneFilterTest.java b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/period/KeepOneFilterTest.java
new file mode 100644 (file)
index 0000000..8e855f9
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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.core.computation.dbcleaner.period;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
+import org.junit.Test;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.core.purge.PurgeableSnapshotDto;
+
+import javax.annotation.Nullable;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.sonar.core.computation.dbcleaner.DbCleanerTestUtils.createSnapshotWithDate;
+
+public class KeepOneFilterTest {
+
+  private static List<Long> snapshotIds(List<PurgeableSnapshotDto> snapshotDtos) {
+    return newArrayList(Iterables.transform(snapshotDtos, new Function<PurgeableSnapshotDto, Long>() {
+      @Override
+      public Long apply(@Nullable PurgeableSnapshotDto input) {
+        return input != null ? input.getSnapshotId() : null;
+      }
+    }));
+  }
+
+  @Test
+  public void shouldOnlyOneSnapshotPerInterval() {
+    Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month");
+
+    List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList(
+      createSnapshotWithDate(1L, "2010-01-01"), // out of scope -> keep
+      createSnapshotWithDate(2L, "2011-05-01"), // may -> keep
+      createSnapshotWithDate(3L, "2011-05-02"), // may -> to be deleted
+      createSnapshotWithDate(4L, "2011-05-19"), // may -> to be deleted
+      createSnapshotWithDate(5L, "2011-06-01"), // june -> keep
+      createSnapshotWithDate(6L, "2012-01-01") // out of scope -> keep
+      ));
+
+    assertThat(toDelete).hasSize(2);
+
+    List<Long> snapshotIds = snapshotIds(toDelete);
+    assertThat(snapshotIds).contains(3L);
+    assertThat(snapshotIds.contains(4L));
+  }
+
+  @Test
+  public void shouldKeepNonDeletableSnapshots() {
+    Filter filter = new KeepOneFilter(DateUtils.parseDate("2011-03-25"), DateUtils.parseDate("2011-08-25"), Calendar.MONTH, "month");
+
+    List<PurgeableSnapshotDto> toDelete = filter.filter(Arrays.<PurgeableSnapshotDto>asList(
+      createSnapshotWithDate(1L, "2011-05-01"), // to be deleted
+      createSnapshotWithDate(2L, "2011-05-02").setLast(true),
+      createSnapshotWithDate(3L, "2011-05-19").setHasEvents(true).setLast(false),
+      createSnapshotWithDate(4L, "2011-05-23") // to be deleted
+      ));
+
+    assertThat(toDelete).hasSize(2);
+
+    List<Long> snapshotIds = snapshotIds(toDelete);
+    assertThat(snapshotIds).contains(1L);
+    assertThat(snapshotIds.contains(4L));
+  }
+
+  @Test
+  public void test_isDeletable() {
+    assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01"))).isTrue();
+    assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setLast(true))).isFalse();
+    assertThat(KeepOneFilter.isDeletable(createSnapshotWithDate(1L, "2011-05-01").setHasEvents(true))).isFalse();
+  }
+
+}