Browse Source

SONAR-249: extract persistence layer from data index + dump measures at the end of the batch instead of persisting them on the fly

tags/2.6
simonbrandhof 13 years ago
parent
commit
19f841e8c1
94 changed files with 2768 additions and 2543 deletions
  1. 3
    2
      plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/TendencyDecorator.java
  2. 15
    4
      sonar-batch/src/main/java/org/sonar/batch/Batch.java
  3. 10
    19
      sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java
  4. 66
    0
      sonar-batch/src/main/java/org/sonar/batch/DefaultMetricFinder.java
  5. 10
    10
      sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java
  6. 35
    15
      sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java
  7. 18
    31
      sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java
  8. 0
    102
      sonar-batch/src/main/java/org/sonar/batch/ViolationsDao.java
  9. 62
    64
      sonar-batch/src/main/java/org/sonar/batch/index/Bucket.java
  10. 442
    0
      sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
  11. 112
    0
      sonar-batch/src/main/java/org/sonar/batch/index/DefaultPersistenceManager.java
  12. 63
    0
      sonar-batch/src/main/java/org/sonar/batch/index/DependencyPersister.java
  13. 65
    0
      sonar-batch/src/main/java/org/sonar/batch/index/EventPersister.java
  14. 68
    0
      sonar-batch/src/main/java/org/sonar/batch/index/LinkPersister.java
  15. 133
    0
      sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java
  16. 61
    0
      sonar-batch/src/main/java/org/sonar/batch/index/PersistenceManager.java
  17. 247
    0
      sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java
  18. 59
    0
      sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java
  19. 79
    0
      sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java
  20. 0
    52
      sonar-batch/src/main/java/org/sonar/batch/indexer/DefaultPersister.java
  21. 0
    470
      sonar-batch/src/main/java/org/sonar/batch/indexer/DefaultSonarIndex.java
  22. 0
    100
      sonar-batch/src/main/java/org/sonar/batch/indexer/LibraryPersister.java
  23. 0
    58
      sonar-batch/src/main/java/org/sonar/batch/indexer/ProjectPersister.java
  24. 0
    96
      sonar-batch/src/main/java/org/sonar/batch/indexer/ResourcePersister.java
  25. 0
    50
      sonar-batch/src/main/java/org/sonar/batch/indexer/ResourcePersisters.java
  26. 11
    10
      sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java
  27. 5
    4
      sonar-batch/src/main/java/org/sonar/batch/phases/MavenPhaseExecutor.java
  28. 4
    4
      sonar-batch/src/main/java/org/sonar/batch/phases/MavenPluginsConfigurator.java
  29. 88
    0
      sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java
  30. 9
    14
      sonar-batch/src/main/java/org/sonar/batch/phases/PostJobsExecutor.java
  31. 6
    4
      sonar-batch/src/main/java/org/sonar/batch/phases/SensorsExecutor.java
  32. 9
    15
      sonar-batch/src/main/java/org/sonar/batch/phases/UpdateStatusJob.java
  33. 0
    29
      sonar-batch/src/test/java/org/sonar/batch/CoreJobsTest.java
  34. 113
    113
      sonar-batch/src/test/java/org/sonar/batch/DefaultTimeMachineTest.java
  35. 110
    0
      sonar-batch/src/test/java/org/sonar/batch/index/BucketTest.java
  36. 4
    6
      sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java
  37. 133
    0
      sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java
  38. 140
    0
      sonar-batch/src/test/java/org/sonar/batch/index/ResourcePersisterTest.java
  39. 0
    61
      sonar-batch/src/test/java/org/sonar/batch/indexer/DefaultPersisterTest.java
  40. 0
    72
      sonar-batch/src/test/java/org/sonar/batch/indexer/DefaultSonarIndexTest.java
  41. 0
    94
      sonar-batch/src/test/java/org/sonar/batch/indexer/LibraryPersisterTest.java
  42. 0
    67
      sonar-batch/src/test/java/org/sonar/batch/indexer/ResourcePersistersTest.java
  43. 4
    4
      sonar-batch/src/test/java/org/sonar/batch/phases/MavenPhaseExecutorTest.java
  44. 2
    4
      sonar-batch/src/test/java/org/sonar/batch/phases/MavenPluginsConfiguratorTest.java
  45. 33
    0
      sonar-batch/src/test/java/org/sonar/batch/phases/PhasesTest.java
  46. 4
    19
      sonar-batch/src/test/java/org/sonar/batch/phases/PostJobsExecutorTest.java
  47. 5
    6
      sonar-batch/src/test/java/org/sonar/batch/phases/UpdateStatusJobTest.java
  48. 0
    22
      sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/doNotFailIfNoPenultimateLast-result.xml
  49. 0
    23
      sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/doNotFailIfNoPenultimateLast.xml
  50. 0
    173
      sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/lastSnapshotIsNotUpdatedWhenAnalyzingPastSnapshot-result.xml
  51. 0
    174
      sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/lastSnapshotIsNotUpdatedWhenAnalyzingPastSnapshot.xml
  52. 0
    38
      sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/sharedFixture.xml
  53. 0
    55
      sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/shouldUnflagPenultimateLastSnapshot-result.xml
  54. 0
    57
      sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/shouldUnflagPenultimateLastSnapshot.xml
  55. 0
    0
      sonar-batch/src/test/resources/org/sonar/batch/MavenProjectBuilderTest/MavenPluginsConfiguratorTest/pom.xml
  56. 31
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shared.xml
  57. 45
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldDelaySaving-result.xml
  58. 35
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertMeasure-result.xml
  59. 42
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldNotDelaySavingWithDatabaseOnlyMeasure-result.xml
  60. 30
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldUpdateMeasure-result.xml
  61. 12
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shared.xml
  62. 30
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewDirectory-result.xml
  63. 34
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewLibrary-result.xml
  64. 48
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewMultiModulesProject-result.xml
  65. 22
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewProject-result.xml
  66. 17
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldUpdateExistingResource-result.xml
  67. 11
    0
      sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldUpdateExistingResource.xml
  68. 0
    23
      sonar-batch/src/test/resources/org/sonar/batch/indexer/DefaultPersisterTest/createResource-result.xml
  69. 0
    12
      sonar-batch/src/test/resources/org/sonar/batch/indexer/DefaultPersisterTest/createResource.xml
  70. 0
    23
      sonar-batch/src/test/resources/org/sonar/batch/indexer/DefaultPersisterTest/updateExistingResource-result.xml
  71. 0
    18
      sonar-batch/src/test/resources/org/sonar/batch/indexer/DefaultPersisterTest/updateExistingResource.xml
  72. 0
    23
      sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/addNewLibraryVersion-result.xml
  73. 0
    19
      sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/addNewLibraryVersion.xml
  74. 0
    19
      sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/createLibrary-result.xml
  75. 0
    11
      sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/createLibrary.xml
  76. 0
    19
      sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/reuseExistingLibrary-result.xml
  77. 0
    19
      sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/reuseExistingLibrary.xml
  78. 19
    0
      sonar-batch/src/test/resources/org/sonar/batch/phases/MavenPluginsConfiguratorTest/pom.xml
  79. 1
    1
      sonar-core/src/main/java/org/sonar/jpa/dao/AsyncMeasuresDao.java
  80. 5
    5
      sonar-core/src/main/java/org/sonar/jpa/dao/AsyncMeasuresService.java
  81. 4
    2
      sonar-core/src/test/java/org/sonar/jpa/session/DatabaseSessionTest.java
  82. 8
    0
      sonar-plugin-api/src/main/java/org/sonar/api/batch/Event.java
  83. 4
    6
      sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java
  84. 24
    0
      sonar-plugin-api/src/main/java/org/sonar/api/batch/TimeMachineQuery.java
  85. 20
    81
      sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureModel.java
  86. 6
    16
      sonar-plugin-api/src/main/java/org/sonar/api/database/model/RuleFailureModel.java
  87. 19
    25
      sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java
  88. 6
    6
      sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java
  89. 12
    16
      sonar-plugin-api/src/main/java/org/sonar/api/measures/MetricFinder.java
  90. 1
    5
      sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java
  91. 43
    43
      sonar-plugin-api/src/test/java/org/sonar/api/database/model/MeasureModelTest.java
  92. 7
    7
      sonar-plugin-api/src/test/java/org/sonar/api/measures/AverageComplexityFormulaTest.java
  93. 2
    2
      sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureUtilsTest.java
  94. 2
    1
      sonar-server/src/main/webapp/WEB-INF/app/models/snapshot.rb

+ 3
- 2
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/TendencyDecorator.java View File

@@ -20,16 +20,17 @@
package org.sonar.plugins.core.sensors;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang.time.DateUtils;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.*;
import org.sonar.jpa.dao.MeasuresDao;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
import org.sonar.jpa.dao.MeasuresDao;

import java.util.ArrayList;
import java.util.List;
@@ -92,7 +93,7 @@ public class TendencyDecorator implements Decorator {
if (shouldDecorateResource(resource)) {
resetQuery(context.getProject(), resource);
List<Object[]> fields = timeMachine.getMeasuresFields(query);
ArrayListMultimap<Metric, Double> valuesPerMetric = ArrayListMultimap.create();
ListMultimap<Metric, Double> valuesPerMetric = ArrayListMultimap.create();
for (Object[] field : fields) {
valuesPerMetric.put((Metric) field[1], (Double) field[2]);
}

+ 15
- 4
sonar-batch/src/main/java/org/sonar/batch/Batch.java View File

@@ -29,8 +29,9 @@ import org.sonar.api.resources.Project;
import org.sonar.api.utils.HttpDownloader;
import org.sonar.api.utils.IocContainer;
import org.sonar.api.utils.ServerHttpClient;
import org.sonar.batch.indexer.DefaultSonarIndex;
import org.sonar.batch.index.*;
import org.sonar.core.plugin.JpaPluginDao;
import org.sonar.jpa.dao.MeasuresDao;
import org.sonar.jpa.session.DatabaseSessionProvider;
import org.sonar.jpa.session.DriverDatabaseConnector;
import org.sonar.jpa.session.ThreadLocalDatabaseSessionFactory;
@@ -70,16 +71,26 @@ public class Batch {
batchContainer.as(Characteristics.CACHE).addComponent(ServerMetadata.class);
batchContainer.as(Characteristics.CACHE).addComponent(ProjectTree.class);
batchContainer.as(Characteristics.CACHE).addComponent(DefaultResourceCreationLock.class);
batchContainer.as(Characteristics.CACHE).addComponent(DefaultSonarIndex.class);
batchContainer.as(Characteristics.CACHE).addComponent(DefaultMetricFinder.class);
batchContainer.as(Characteristics.CACHE).addComponent(DefaultIndex.class);
batchContainer.as(Characteristics.CACHE).addComponent(DefaultPersistenceManager.class);
batchContainer.as(Characteristics.CACHE).addComponent(DependencyPersister.class);
batchContainer.as(Characteristics.CACHE).addComponent(EventPersister.class);
batchContainer.as(Characteristics.CACHE).addComponent(LinkPersister.class);
batchContainer.as(Characteristics.CACHE).addComponent(MeasurePersister.class);
batchContainer.as(Characteristics.CACHE).addComponent(ResourcePersister.class);
batchContainer.as(Characteristics.CACHE).addComponent(SourcePersister.class);
batchContainer.as(Characteristics.CACHE).addComponent(ViolationPersister.class);
batchContainer.as(Characteristics.CACHE).addComponent(JpaPluginDao.class);
batchContainer.as(Characteristics.CACHE).addComponent(BatchPluginRepository.class);
batchContainer.as(Characteristics.CACHE).addComponent(Plugins.class);
batchContainer.as(Characteristics.CACHE).addComponent(ServerHttpClient.class);
batchContainer.as(Characteristics.CACHE).addComponent(HttpDownloader.class);
batchContainer.as(Characteristics.CACHE).addComponent(MeasuresDao.class);
batchContainer.start();

ProjectTree projectTree = batchContainer.getComponent(ProjectTree.class);
DefaultSonarIndex index = batchContainer.getComponent(DefaultSonarIndex.class);
DefaultIndex index = batchContainer.getComponent(DefaultIndex.class);
analyzeProject(batchContainer, index, projectTree.getRootProject());

// batchContainer is stopped by its parent
@@ -106,7 +117,7 @@ public class Batch {
container.as(Characteristics.CACHE).addComponent(component);
}

private void analyzeProject(MutablePicoContainer container, DefaultSonarIndex index, Project project) {
private void analyzeProject(MutablePicoContainer container, DefaultIndex index, Project project) {
for (Project module : project.getModules()) {
analyzeProject(container, index, module);
}

+ 10
- 19
sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java View File

@@ -30,31 +30,27 @@ import org.sonar.api.measures.Metric;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Violation;
import org.sonar.batch.indexer.Bucket;
import org.sonar.batch.indexer.DefaultSonarIndex;
import org.sonar.batch.index.DefaultIndex;

import java.util.*;

public class DefaultDecoratorContext implements DecoratorContext {

private DatabaseSession session;
private DefaultSonarIndex index;
private DefaultIndex index;
private Resource resource;
private boolean readOnly = false;

private List<DecoratorContext> childrenContexts;
private ViolationsDao violationsDao;

public DefaultDecoratorContext(Resource resource,
DefaultSonarIndex index,
DefaultIndex index,
List<DecoratorContext> childrenContexts,
DatabaseSession session,
ViolationsDao violationsDao) {
DatabaseSession session) {
this.index = index;
this.session = session;
this.resource = resource;
this.childrenContexts = childrenContexts;
this.violationsDao = violationsDao;
}

public DefaultDecoratorContext setReadOnly(boolean b) {
@@ -111,29 +107,24 @@ public class DefaultDecoratorContext implements DecoratorContext {

public DecoratorContext saveMeasure(Measure measure) {
checkReadOnly("saveMeasure");
index.saveMeasure(resource, measure);
index.addMeasure(resource, measure);
return this;
}

public DecoratorContext saveMeasure(Metric metric, Double value) {
checkReadOnly("saveMeasure");
index.saveMeasure(resource, new Measure(metric, value));
index.addMeasure(resource, new Measure(metric, value));
return this;
}


public List<Violation> getViolations() {
Bucket bucket = index.getBucket(resource);
if (bucket != null && bucket.getSnapshotId() != null) {
return violationsDao.getViolations(resource, bucket.getSnapshotId());
}

return null;
return index.getViolations(resource);
}

public Dependency saveDependency(Dependency dependency) {
checkReadOnly("saveDependency");
return index.saveDependency(dependency);
checkReadOnly("addDependency");
return index.addDependency(dependency);
}

public Set<Dependency> getDependencies() {
@@ -157,7 +148,7 @@ public class DefaultDecoratorContext implements DecoratorContext {
}

public Event createEvent(String name, String description, String category, Date date) {
return index.createEvent(resource, name, description, category, date);
return index.addEvent(resource, name, description, category, date);
}

public void deleteEvent(Event event) {

+ 66
- 0
sonar-batch/src/main/java/org/sonar/batch/DefaultMetricFinder.java View File

@@ -0,0 +1,66 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.MetricFinder;

import java.util.Collection;
import java.util.List;
import java.util.Map;

public final class DefaultMetricFinder implements MetricFinder {

private DatabaseSession session;
private Map<String, Metric> metrics = Maps.newHashMap();

public DefaultMetricFinder(DatabaseSession session) {
this.session = session;
}

public void start() {
List<Metric> list = session.getResults(Metric.class, "enabled", true);
for (Metric metric : list) {
metrics.put(metric.getKey(), metric);
}
}

public Metric find(String key) {
return metrics.get(key);
}

public Collection<Metric> findAll(List<String> metricKeys) {
List<Metric> result = Lists.newLinkedList();
for (String metricKey : metricKeys) {
Metric metric = find(metricKey);
if (metric != null) {
result.add(metric);
}
}
return result;
}

public Collection<Metric> findAll() {
return metrics.values();
}
}

+ 10
- 10
sonar-batch/src/main/java/org/sonar/batch/DefaultSensorContext.java View File

@@ -29,7 +29,7 @@ import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectLink;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Violation;
import org.sonar.batch.indexer.DefaultSonarIndex;
import org.sonar.batch.index.DefaultIndex;

import java.util.Collection;
import java.util.Date;
@@ -38,10 +38,10 @@ import java.util.Set;

public class DefaultSensorContext implements SensorContext {

private DefaultSonarIndex index;
private DefaultIndex index;
private Project project;

public DefaultSensorContext(DefaultSonarIndex index, Project project) {
public DefaultSensorContext(DefaultIndex index, Project project) {
this.index = index;
this.project = project;
}
@@ -59,11 +59,11 @@ public class DefaultSensorContext implements SensorContext {
}

public Measure saveMeasure(Measure measure) {
return index.saveMeasure(project, measure);
return index.addMeasure(project, measure);
}

public Measure saveMeasure(Metric metric, Double value) {
return index.saveMeasure(project, new Measure(metric, value));
return index.addMeasure(project, new Measure(metric, value));
}

public Measure getMeasure(Resource resource, Metric metric) {
@@ -87,11 +87,11 @@ public class DefaultSensorContext implements SensorContext {
}

public Measure saveMeasure(Resource resource, Metric metric, Double value) {
return index.saveMeasure(resourceOrProject(resource), new Measure(metric, value));
return index.addMeasure(resourceOrProject(resource), new Measure(metric, value));
}

public Measure saveMeasure(Resource resource, Measure measure) {
return index.saveMeasure(resourceOrProject(resource), measure);
return index.addMeasure(resourceOrProject(resource), measure);
}

public void saveViolation(Violation violation) {
@@ -110,7 +110,7 @@ public class DefaultSensorContext implements SensorContext {
}

public Dependency saveDependency(Dependency dependency) {
return index.saveDependency(dependency);
return index.addDependency(dependency);
}

public Set<Dependency> getDependencies() {
@@ -130,7 +130,7 @@ public class DefaultSensorContext implements SensorContext {
}

public void saveLink(ProjectLink link) {
index.saveLink(link);
index.addLink(link);
}

public void deleteLink(String key) {
@@ -142,7 +142,7 @@ public class DefaultSensorContext implements SensorContext {
}

public Event createEvent(Resource resource, String name, String description, String category, Date date) {
return index.createEvent(resource, name, description, category, date);
return index.addEvent(resource, name, description, category, date);
}

public void deleteEvent(Event event) {

+ 35
- 15
sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java View File

@@ -19,14 +19,18 @@
*/
package org.sonar.batch;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.sonar.api.batch.TimeMachine;
import org.sonar.api.batch.TimeMachineQuery;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.MeasureModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.MetricFinder;
import org.sonar.api.resources.Resource;
import org.sonar.batch.indexer.DefaultSonarIndex;
import org.sonar.batch.index.DefaultIndex;
import org.sonar.jpa.dao.MeasuresDao;

import java.util.*;
@@ -35,22 +39,24 @@ import javax.persistence.Query;
public class DefaultTimeMachine implements TimeMachine {

private DatabaseSession session;
private DefaultSonarIndex index;
private MeasuresDao measuresDao;
private DefaultIndex index;
private MetricFinder metricFinder;

public DefaultTimeMachine(DatabaseSession session, DefaultSonarIndex index, MeasuresDao measuresDao) {
public DefaultTimeMachine(DatabaseSession session, DefaultIndex index, MetricFinder metricFinder) {
this.session = session;
this.index = index;
this.measuresDao = measuresDao;
this.metricFinder = metricFinder;
}

public List<Measure> getMeasures(TimeMachineQuery query) {
List<Object[]> objects = execute(query, true);
List<Measure> result = new ArrayList<Measure>();
Map<Integer, Metric> metricById = getMetricsById(query);

List<Object[]> objects = execute(query, true, metricById.keySet());
List<Measure> result = Lists.newArrayList();

for (Object[] object : objects) {
MeasureModel model = (MeasureModel) object[0];
Measure measure = model.toMeasure();
Measure measure = model.toMeasure(metricById.get(model.getMetricId()));
measure.setDate((Date) object[1]);
result.add(measure);
}
@@ -58,10 +64,15 @@ public class DefaultTimeMachine implements TimeMachine {
}

public List<Object[]> getMeasuresFields(TimeMachineQuery query) {
return execute(query, false);
Map<Integer, Metric> metricById = getMetricsById(query);
List<Object[]> rows = execute(query, false, metricById.keySet());
for (Object[] fields : rows) {
fields[1]=metricById.get(fields[1]);
}
return rows;
}

protected List execute(TimeMachineQuery query, boolean selectAllFields) {
protected List execute(TimeMachineQuery query, boolean selectAllFields, Set<Integer> metricIds) {
Resource resource = query.getResource();
if (resource!=null && resource.getId()==null) {
resource = index.getResource(query.getResource());
@@ -71,21 +82,21 @@ public class DefaultTimeMachine implements TimeMachine {
}

StringBuilder sb = new StringBuilder();
Map<String, Object> params = new HashMap<String, Object>();
Map<String, Object> params = Maps.newHashMap();

if (selectAllFields) {
sb.append("SELECT m, s.createdAt ");
} else {
sb.append("SELECT s.createdAt, m.metric, m.value ");
sb.append("SELECT s.createdAt, m.metricId, m.value ");
}
sb.append(" FROM " + MeasureModel.class.getSimpleName() + " m, " + Snapshot.class.getSimpleName() + " s WHERE m.snapshotId=s.id AND s.resourceId=:resourceId AND s.status=:status AND m.characteristic IS NULL ");
params.put("resourceId", resource.getId());
params.put("status", Snapshot.STATUS_PROCESSED);

sb.append(" AND m.rule IS NULL AND m.rulePriority IS NULL AND m.rulesCategoryId IS NULL ");
if (query.getMetrics() != null) {
sb.append(" AND m.metric IN (:metrics) ");
params.put("metrics", measuresDao.getMetrics(query.getMetrics()));
if (!metricIds.isEmpty()) {
sb.append(" AND m.metricId IN (:metricIds) ");
params.put("metricIds", metricIds);
}
if (query.isFromCurrentAnalysis()) {
sb.append(" AND s.createdAt>=:from ");
@@ -116,4 +127,13 @@ public class DefaultTimeMachine implements TimeMachine {
}
return jpaQuery.getResultList();
}

public Map<Integer, Metric> getMetricsById(TimeMachineQuery query) {
Collection<Metric> metrics = metricFinder.findAll(query.getMetricKeys());
Map<Integer, Metric> result = Maps.newHashMap();
for (Metric metric : metrics) {
result.put(metric.getId(), metric);
}
return result;
}
}

+ 18
- 31
sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java View File

@@ -19,18 +19,15 @@
*/
package org.sonar.batch;

import java.util.List;

import org.picocontainer.Characteristics;
import org.picocontainer.MutablePicoContainer;
import org.sonar.api.batch.BatchExtensionDictionnary;
import org.sonar.api.batch.FileFilter;
import org.sonar.api.batch.ProjectClasspath;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.Metrics;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.DefaultProjectFileSystem;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Languages;
@@ -38,15 +35,14 @@ import org.sonar.api.resources.Project;
import org.sonar.api.rules.DefaultRulesManager;
import org.sonar.api.utils.IocContainer;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.indexer.DefaultSonarIndex;
import org.sonar.batch.index.DefaultIndex;
import org.sonar.batch.index.ResourcePersister;
import org.sonar.batch.phases.Phases;
import org.sonar.core.qualitymodel.DefaultModelFinder;
import org.sonar.core.rule.DefaultRuleFinder;
import org.sonar.jpa.dao.AsyncMeasuresDao;
import org.sonar.jpa.dao.AsyncMeasuresService;
import org.sonar.jpa.dao.DaoFacade;
import org.sonar.jpa.dao.MeasuresDao;
import org.sonar.jpa.dao.ProfilesDao;
import org.sonar.jpa.dao.RulesDao;
import org.sonar.jpa.dao.*;

import java.util.List;

public class ProjectBatch {

@@ -57,29 +53,22 @@ public class ProjectBatch {
this.globalContainer = container;
}

public void execute(DefaultSonarIndex index, Project project) {
public void execute(DefaultIndex index, Project project) {
try {
startChildContainer(index, project);
SensorContext sensorContext = batchContainer.getComponent(SensorContext.class);
for (Class<? extends CoreJob> clazz : CoreJobs.allJobs()) {
CoreJob job = getComponent(clazz);
job.execute(project, sensorContext);
commit();
}
batchContainer.getComponent(Phases.class).execute(project);

} finally {
index.clear();
stop();
}
}

public void startChildContainer(DefaultSonarIndex index, Project project) {
public void startChildContainer(DefaultIndex index, Project project) {
batchContainer = globalContainer.makeChildContainer();

batchContainer.as(Characteristics.CACHE).addComponent(project);
batchContainer.as(Characteristics.CACHE).addComponent(project.getPom());
batchContainer.as(Characteristics.CACHE).addComponent(ProjectClasspath.class);
batchContainer.as(Characteristics.CACHE).addComponent(index.getBucket(project).getSnapshot());
batchContainer.as(Characteristics.CACHE).addComponent(project.getConfiguration());

// need to be registered after the Configuration
@@ -87,8 +76,11 @@ public class ProjectBatch {

batchContainer.as(Characteristics.CACHE).addComponent(DaoFacade.class);
batchContainer.as(Characteristics.CACHE).addComponent(RulesDao.class);

// the Snapshot component will be removed when asynchronous measures are improved (required for AsynchronousMeasureSensor)
batchContainer.as(Characteristics.CACHE).addComponent(globalContainer.getComponent(ResourcePersister.class).getSnapshot(project));

batchContainer.as(Characteristics.CACHE).addComponent(org.sonar.api.database.daos.RulesDao.class);
batchContainer.as(Characteristics.CACHE).addComponent(MeasuresDao.class);
batchContainer.as(Characteristics.CACHE).addComponent(org.sonar.api.database.daos.MeasuresDao.class);
batchContainer.as(Characteristics.CACHE).addComponent(ProfilesDao.class);
batchContainer.as(Characteristics.CACHE).addComponent(AsyncMeasuresDao.class);
@@ -98,7 +90,6 @@ public class ProjectBatch {
batchContainer.as(Characteristics.CACHE).addComponent(Languages.class);
batchContainer.as(Characteristics.CACHE).addComponent(BatchExtensionDictionnary.class);
batchContainer.as(Characteristics.CACHE).addComponent(DefaultTimeMachine.class);
batchContainer.as(Characteristics.CACHE).addComponent(ViolationsDao.class);
batchContainer.as(Characteristics.CACHE).addComponent(ViolationFilters.class);
batchContainer.as(Characteristics.CACHE).addComponent(ResourceFilters.class);
batchContainer.as(Characteristics.CACHE).addComponent(DefaultModelFinder.class);
@@ -113,21 +104,21 @@ public class ProjectBatch {
prepareProject(project, index);
}

private void prepareProject(Project project, DefaultSonarIndex index) {
private void prepareProject(Project project, DefaultIndex index) {
Language language = getComponent(Languages.class).get(project.getLanguageKey());
if (language == null) {
throw new SonarException("Language with key '" + project.getLanguageKey() + "' not found");
}
project.setLanguage(language);
index.selectProject(project, getComponent(ResourceFilters.class), getComponent(ViolationFilters.class),
getComponent(MeasuresDao.class), getComponent(ViolationsDao.class));
index.setCurrentProject(project, getComponent(ResourceFilters.class), getComponent(ViolationFilters.class), getComponent(RulesProfile.class));

List<FileFilter> fileFilters = batchContainer.getComponents(FileFilter.class);
((DefaultProjectFileSystem) project.getFileSystem()).addFileFilters(fileFilters);
}

private void loadCoreComponents(MutablePicoContainer container) {
for (Class<?> clazz : CoreJobs.allJobs()) {
container.as(Characteristics.CACHE).addComponent(Phases.class);
for (Class clazz : Phases.getPhaseClasses()) {
container.as(Characteristics.CACHE).addComponent(clazz);
}
for (Metric metric : CoreMetrics.getMetrics()) {
@@ -142,7 +133,6 @@ public class ProjectBatch {

private void stop() {
if (batchContainer != null) {
commit();
try {
globalContainer.removeChildContainer(batchContainer);
batchContainer.stop();
@@ -153,9 +143,6 @@ public class ProjectBatch {
}
}

public void commit() {
getComponent(DatabaseSession.class).commit();
}

public <T> T getComponent(Class<T> clazz) {
if (batchContainer != null) {

+ 0
- 102
sonar-batch/src/main/java/org/sonar/batch/ViolationsDao.java View File

@@ -1,102 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;

import org.slf4j.LoggerFactory;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.RuleFailureModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.Violation;
import org.sonar.jpa.dao.RulesDao;

import java.util.ArrayList;
import java.util.List;

public class ViolationsDao {

private RulesProfile profile;
private DatabaseSession session;
private RulesDao rulesDao;
private boolean reuseExistingRulesConfig;

public ViolationsDao(RulesProfile profile, DatabaseSession session, RulesDao rulesDao, Project project) {
this.profile = profile;
this.session = session;
this.rulesDao = rulesDao;
this.reuseExistingRulesConfig = project.getReuseExistingRulesConfig();
}

public List<Violation> getViolations(Resource resource, Integer snapshotId) {
List<RuleFailureModel> models = session.getResults(RuleFailureModel.class, "snapshotId", snapshotId);
List<Violation> violations = new ArrayList<Violation>();
for (RuleFailureModel model : models) {
Violation violation = Violation.create(model.getRule(), resource);
violation.setLineId(model.getLine());
violation.setMessage(model.getMessage());
violation.setPriority(model.getPriority());
violation.setCost(model.getCost());
violations.add(violation);
}
return violations;
}

public void saveViolation(Snapshot snapshot, Violation violation) {
if (profile == null || snapshot == null || violation == null || violation.getRule() == null) {
throw new IllegalArgumentException("Missing data to save violation : profile=" + profile + ",snapshot=" + snapshot + ",violation=" + violation);
}

ActiveRule activeRule = profile.getActiveRule(violation.getRule());
if (activeRule == null) {
if (reuseExistingRulesConfig) {
activeRule = new ActiveRule(profile, violation.getRule(), violation.getRule().getPriority());
} else {
LoggerFactory.getLogger(getClass()).debug("Violation is not saved because rule is not activated : violation={}", violation);
}
}
if (activeRule != null) {
RuleFailureModel model = toModel(snapshot, violation, activeRule);
session.save(model);
}
}

private RuleFailureModel toModel(Snapshot snapshot, Violation violation, ActiveRule activeRule) {
Rule rule = reload(violation.getRule());
if (rule == null) {
throw new IllegalArgumentException("Rule does not exist : " + violation.getRule());
}
RuleFailureModel model = new RuleFailureModel(rule, activeRule.getPriority());
violation.setPriority(activeRule.getPriority());
model.setLine(violation.getLineId());
model.setMessage(violation.getMessage());
model.setCost(violation.getCost());
model.setSnapshotId(snapshot.getId());

return model;
}

private Rule reload(Rule rule) {
return rule.getId() != null ? rule : rulesDao.getRuleByKey(rule.getPluginName(), rule.getKey());
}
}

sonar-batch/src/main/java/org/sonar/batch/indexer/Bucket.java → sonar-batch/src/main/java/org/sonar/batch/index/Bucket.java View File

@@ -17,64 +17,39 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.indexer;
package org.sonar.batch.index;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
import org.sonar.api.measures.MeasuresFilters;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Violation;
import org.sonar.api.utils.SonarException;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class Bucket<RESOURCE extends Resource> {
public final class Bucket {

private RESOURCE resource;
private Snapshot snapshot;
private Resource resource;
private ListMultimap<String, Measure> measuresByMetric = ArrayListMultimap.create();
private boolean sourceSaved = false;
private Bucket<Project> project;
private Bucket<?> parent;
private List<Bucket<?>> children;
private List<Violation> violations = Lists.newLinkedList();

public Bucket(RESOURCE resource) {
private Bucket parent;
private List<Bucket> children;

public Bucket(Resource resource) {
this.resource = resource;
}

public RESOURCE getResource() {
public Resource getResource() {
return resource;
}

public Bucket<Project> getProject() {
return project;
}

public Bucket<RESOURCE> setProject(Bucket<Project> project) {
this.project = project;
return this;
}

public Snapshot getSnapshot() {
return snapshot;
}

public Integer getSnapshotId() {
if (snapshot != null) {
return snapshot.getId();
}
return null;
}

public void setSnapshot(Snapshot snapshot) {
this.snapshot = snapshot;
}

public void setParent(Bucket parent) {
this.parent = parent;
if (parent != null) {
@@ -82,69 +57,92 @@ public class Bucket<RESOURCE extends Resource> {
}
}

private void addChild(Bucket bucket) {
private void addChild(Bucket child) {
if (children == null) {
children = Lists.newArrayList();
}
children.add(bucket);
children.add(child);
}

private void removeChild(Bucket bucket) {
private void removeChild(Bucket child) {
if (children != null) {
children.remove(bucket);
children.remove(child);
}
}

public List<Bucket<?>> getChildren() {
if (children == null) {
return Collections.emptyList();
}
return children;
public List<Bucket> getChildren() {
return (children == null ? Collections.<Bucket>emptyList() : children);
}

public Bucket getParent() {
return parent;
}

public void addMeasure(Measure measure) {
measuresByMetric.put(measure.getMetric().getKey(), measure);
public void addViolation(Violation violation) {
violations.add(violation);
}

public boolean isSourceSaved() {
return sourceSaved;
public List<Violation> getViolations() {
return violations;
}

public void setSourceSaved(boolean b) {
this.sourceSaved = b;
public void addMeasure(Measure measure) {
List<Measure> metricMeasures = measuresByMetric.get(measure.getMetric().getKey());

boolean add = true;
if (metricMeasures != null) {
int index = metricMeasures.indexOf(measure);
if (index > -1) {
if (metricMeasures.get(index) == measure) {
add = false;
} else {
throw new SonarException("Can not add twice the same measure: " + measure);
}
}
}
if (add) {
measuresByMetric.put(measure.getMetric().getKey(), measure);
}
}

public void clear() {
measuresByMetric = null;
violations = null;
children = null;
if (parent != null) {
parent.removeChild(this);
parent = null;
}
}

public boolean isExcluded() {
return resource.isExcluded();
}

public boolean isPersisted() {
return resource.getId() != null;
}

public Integer getResourceId() {
return resource.getId();
}

public <M> M getMeasures(final MeasuresFilter<M> filter) {
Collection<Measure> unfiltered;
if (filter instanceof MeasuresFilters.MetricFilter) {
unfiltered = measuresByMetric.get(((MeasuresFilters.MetricFilter) filter).filterOnMetric().getKey());
unfiltered = measuresByMetric.get(((MeasuresFilters.MetricFilter) filter).filterOnMetricKey());
} else {
unfiltered = measuresByMetric.values();
}
return filter.filter(unfiltered);
}

public boolean isExcluded() {
return resource.isExcluded();
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Bucket that = (Bucket) o;
return resource.equals(that.resource);
}

@Override
public int hashCode() {
return resource.hashCode();
}
}

+ 442
- 0
sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java View File

@@ -0,0 +1,442 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.Event;
import org.sonar.api.batch.SonarIndex;
import org.sonar.api.design.Dependency;
import org.sonar.api.measures.*;
import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectLink;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.Violation;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.DefaultResourceCreationLock;
import org.sonar.batch.ProjectTree;
import org.sonar.batch.ResourceFilters;
import org.sonar.batch.ViolationFilters;

import java.util.*;

public final class DefaultIndex extends SonarIndex {

private static final Logger LOG = LoggerFactory.getLogger(DefaultIndex.class);

private RulesProfile profile;
private PersistenceManager persistence;
private DefaultResourceCreationLock lock;
private MetricFinder metricFinder;

// filters
private ViolationFilters violationFilters;
private ResourceFilters resourceFilters;

// caches
private Project currentProject;
private Map<Resource, Bucket> buckets = Maps.newHashMap();
private Set<Dependency> dependencies = Sets.newHashSet();
private Map<Resource, Map<Resource, Dependency>> outgoingDependenciesByResource = Maps.newHashMap();
private Map<Resource, Map<Resource, Dependency>> incomingDependenciesByResource = Maps.newHashMap();
private ProjectTree projectTree;

public DefaultIndex(PersistenceManager persistence, DefaultResourceCreationLock lock, ProjectTree projectTree, MetricFinder metricFinder) {
this.persistence = persistence;
this.lock = lock;
this.projectTree = projectTree;
this.metricFinder = metricFinder;
}

public void start() {
Project rootProject = projectTree.getRootProject();
Bucket bucket = new Bucket(rootProject);
buckets.put(rootProject, bucket);
persistence.saveProject(rootProject);
currentProject = rootProject;

for (Project project : rootProject.getModules()) {
addProject(project);
}
}

private void addProject(Project project) {
addResource(project);
for (Project module : project.getModules()) {
addProject(module);
}
}

public Project getProject() {
return currentProject;
}

public void setCurrentProject(Project project, ResourceFilters resourceFilters, ViolationFilters violationFilters, RulesProfile profile) {
this.currentProject = project;

// the following components depend on the current project, so they need to be reloaded.
this.resourceFilters = resourceFilters;
this.violationFilters = violationFilters;
this.profile = profile;
}

public PersistenceManager getPersistenceManager() {
return persistence;
}

/**
* Keep only project stuff
*/
public void clear() {
Iterator<Map.Entry<Resource, Bucket>> it = buckets.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Resource, Bucket> entry = it.next();
Resource resource = entry.getKey();
if (!ResourceUtils.isSet(resource)) {
entry.getValue().clear();
it.remove();
}
}

Set<Dependency> projectDependencies = getDependenciesBetweenProjects();
dependencies.clear();
incomingDependenciesByResource.clear();
outgoingDependenciesByResource.clear();
for (Dependency projectDependency : projectDependencies) {
projectDependency.setId(null);
registerDependency(projectDependency);
}

lock.unlock();
}


/**
* Does nothing if the resource is already registered.
*
* @param resource
*/
public Resource addResource(Resource resource) {
getOrAddBucket(resource);
return resource;
}

public Resource getResource(Resource resource) {
Bucket bucket = buckets.get(resource);
if (bucket != null) {
return bucket.getResource();
}
return null;
}

private Bucket getOrAddBucket(Resource resource) {
Bucket bucket = buckets.get(resource);
if (bucket != null) {
return bucket;
}

if (lock.isLocked() && !ResourceUtils.isLibrary(resource)) {
LOG.warn("The following resource has not been registered before saving data: " + resource);
}

bucket = new Bucket(resource);
Bucket parentBucket = null;
Resource parent = resource.getParent();
if (parent != null) {
parentBucket = getOrAddBucket(parent);
} else if (!ResourceUtils.isLibrary(resource)) {
parentBucket = buckets.get(currentProject);
}
bucket.setParent(parentBucket);
buckets.put(resource, bucket);

boolean excluded = checkExclusion(resource, parentBucket);
if (!excluded) {
persistence.saveResource(currentProject, resource);
}
return bucket;
}

private boolean checkExclusion(Resource resource, Bucket parent) {
boolean excluded = (parent != null && parent.isExcluded()) || (resourceFilters != null && resourceFilters.isExcluded(resource));
resource.setExcluded(excluded);
return excluded;
}


public List<Resource> getChildren(Resource resource) {
List<Resource> children = Lists.newArrayList();
Bucket bucket = buckets.get(resource);
if (bucket != null) {
for (Bucket childBucket : bucket.getChildren()) {
children.add(childBucket.getResource());
}
}
return children;
}

public Resource getParent(Resource resource) {
Bucket bucket = buckets.get(resource);
if (bucket != null && bucket.getParent() != null) {
return bucket.getParent().getResource();
}
return null;
}

public Measure getMeasure(Resource resource, Metric metric) {
Bucket bucket = buckets.get(resource);
if (bucket != null) {
return bucket.getMeasures(MeasuresFilters.metric(metric));
}
return null;
}

public <M> M getMeasures(Resource resource, MeasuresFilter<M> filter) {
Bucket bucket = buckets.get(resource);
if (bucket != null) {
return bucket.getMeasures(filter);
}
return null;
}

/**
* the measure is updated if it's already registered.
*/
public Measure addMeasure(Resource resource, Measure measure) {
Bucket bucket = getOrAddBucket(resource);
if (!bucket.isExcluded()) {
Metric metric = metricFinder.find(measure.getMetricKey());
if (metric == null) {
throw new SonarException("Unknown metric: " + measure.getMetricKey());
}
measure.setMetric(metric);
if (measure.getPersistenceMode().useMemory()) {
bucket.addMeasure(measure);
}
if (measure.getPersistenceMode().useDatabase()) {
persistence.saveMeasure(currentProject, resource, measure);
}

// TODO keep database measures in cache but remove data
}
return measure;
}

public void setSource(Resource resource, String source) {
Bucket bucket = getOrAddBucket(resource);
if (!bucket.isExcluded()) {
persistence.setSource(currentProject, resource, source);
}
}


//
//
//
// DEPENDENCIES
//
//
//
public Dependency addDependency(Dependency dependency) {
Dependency existingDep = getEdge(dependency.getFrom(), dependency.getTo());
if (existingDep != null) {
return existingDep;
}

Dependency parentDependency = dependency.getParent();
if (parentDependency != null) {
addDependency(parentDependency);
}

persistence.saveDependency(currentProject, dependency, parentDependency);
registerDependency(dependency);
return dependency;
}

protected void registerDependency(Dependency dependency) {
dependencies.add(dependency);
registerOutgoingDependency(dependency);
registerIncomingDependency(dependency);
}

private void registerOutgoingDependency(Dependency dependency) {
Map<Resource, Dependency> outgoingDeps = outgoingDependenciesByResource.get(dependency.getFrom());
if (outgoingDeps == null) {
outgoingDeps = new HashMap<Resource, Dependency>();
outgoingDependenciesByResource.put(dependency.getFrom(), outgoingDeps);
}
outgoingDeps.put(dependency.getTo(), dependency);
}

private void registerIncomingDependency(Dependency dependency) {
Map<Resource, Dependency> incomingDeps = incomingDependenciesByResource.get(dependency.getTo());
if (incomingDeps == null) {
incomingDeps = new HashMap<Resource, Dependency>();
incomingDependenciesByResource.put(dependency.getTo(), incomingDeps);
}
incomingDeps.put(dependency.getFrom(), dependency);
}

public Set<Dependency> getDependencies() {
return dependencies;
}

public Dependency getEdge(Resource from, Resource to) {
Map<Resource, Dependency> map = outgoingDependenciesByResource.get(from);
if (map != null) {
return map.get(to);
}
return null;
}

public boolean hasEdge(Resource from, Resource to) {
return getEdge(from, to) != null;
}

public Set<Resource> getVertices() {
return buckets.keySet();
}

public Collection<Dependency> getOutgoingEdges(Resource from) {
Map<Resource, Dependency> deps = outgoingDependenciesByResource.get(from);
if (deps != null) {
return deps.values();
}
return Collections.emptyList();
}

public Collection<Dependency> getIncomingEdges(Resource to) {
Map<Resource, Dependency> deps = incomingDependenciesByResource.get(to);
if (deps != null) {
return deps.values();
}
return Collections.emptyList();
}

Set<Dependency> getDependenciesBetweenProjects() {
Set<Dependency> result = Sets.newLinkedHashSet();
for (Dependency dependency : dependencies) {
if (ResourceUtils.isSet(dependency.getFrom()) || ResourceUtils.isSet(dependency.getTo())) {
result.add(dependency);
}
}
return result;
}


//
//
//
// VIOLATIONS
//
//
//

public List<Violation> getViolations(Resource resource) {
Bucket bucket = buckets.get(resource);
if (bucket == null) {
return Collections.emptyList();
}
return bucket.getViolations();
}

public void addViolation(Violation violation) {
addViolation(violation, false);
}

public void addViolation(Violation violation, boolean force) {
Bucket bucket;
Resource resource = violation.getResource();
if (resource == null) {
violation.setResource(currentProject);
}
bucket = getOrAddBucket(violation.getResource());
if (!bucket.isExcluded()) {
boolean isIgnored = !force && violationFilters != null && violationFilters.isIgnored(violation);
if (!isIgnored) {
ActiveRule activeRule = profile.getActiveRule(violation.getRule());
if (activeRule == null) {
if (currentProject.getReuseExistingRulesConfig()) {
violation.setPriority(violation.getRule().getPriority());
doAddViolation(violation, bucket);

} else {
LoggerFactory.getLogger(getClass()).debug("Rule is not activated, ignoring violation {}", violation);
}

} else {
violation.setPriority(activeRule.getPriority());
doAddViolation(violation, bucket);
}
}
}
}

private void doAddViolation(Violation violation, Bucket bucket) {
bucket.addViolation(violation);
persistence.saveViolation(currentProject, violation);
}

//
//
//
// LINKS
//
//
//
public void addLink(ProjectLink link) {
persistence.saveLink(currentProject, link);
}

public void deleteLink(String key) {
persistence.deleteLink(currentProject, key);
}


//
//
//
// EVENTS
//
//
//

public List<Event> getEvents(Resource resource) {
// currently events are not cached in memory
return persistence.getEvents(resource);
}

public void deleteEvent(Event event) {
persistence.deleteEvent(event);
}

public Event addEvent(Resource resource, String name, String description, String category, Date date) {
Event event = new Event(name, description, category);
event.setDate(date);
persistence.saveEvent(currentProject, resource, event);
return null;
}
}

+ 112
- 0
sonar-batch/src/main/java/org/sonar/batch/index/DefaultPersistenceManager.java View File

@@ -0,0 +1,112 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import org.sonar.api.batch.Event;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.design.Dependency;
import org.sonar.api.measures.Measure;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectLink;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Violation;

import java.util.List;

public final class DefaultPersistenceManager implements PersistenceManager {

private ResourcePersister resourcePersister;
private SourcePersister sourcePersister;
private MeasurePersister measurePersister;
private DependencyPersister dependencyPersister;
private ViolationPersister violationPersister;
private LinkPersister linkPersister;
private EventPersister eventPersister;

public DefaultPersistenceManager(ResourcePersister resourcePersister, SourcePersister sourcePersister,
MeasurePersister measurePersister, DependencyPersister dependencyPersister,
ViolationPersister violationPersister, LinkPersister linkPersister,
EventPersister eventPersister) {
this.resourcePersister = resourcePersister;
this.sourcePersister = sourcePersister;
this.measurePersister = measurePersister;
this.dependencyPersister = dependencyPersister;
this.violationPersister = violationPersister;
this.linkPersister = linkPersister;
this.eventPersister = eventPersister;
}

public void clear() {
resourcePersister.clear();
sourcePersister.clear();
}

public void setDelayedMode(boolean b) {
measurePersister.setDelayedMode(b);
}

public void dump() {
measurePersister.dump();
}

public void saveProject(Project project) {
resourcePersister.saveProject(project);
}

public Snapshot saveResource(Project project, Resource resource) {
return resourcePersister.saveResource(project, resource);
}

public void setSource(Project project, Resource resource, String source) {
sourcePersister.saveSource(project, resource, source);
}

public void saveMeasure(Project project, Resource resource, Measure measure) {
measurePersister.saveMeasure(project, resource, measure);
}

public void saveDependency(Project project, Dependency dependency, Dependency parentDependency) {
dependencyPersister.saveDependency(project, dependency, parentDependency);
}

public void saveViolation(Project project, Violation violation) {
violationPersister.saveViolation(project, violation);
}

public void saveLink(Project project, ProjectLink link) {
linkPersister.saveLink(project, link);
}

public void deleteLink(Project project, String key) {
linkPersister.deleteLink(project, key);
}

public List<Event> getEvents(Resource resource) {
return eventPersister.getEvents(resource);
}

public void deleteEvent(Event event) {
eventPersister.deleteEvent(event);
}

public void saveEvent(Project project, Resource resource, Event event) {
eventPersister.saveEvent(project, resource, event);
}
}

+ 63
- 0
sonar-batch/src/main/java/org/sonar/batch/index/DependencyPersister.java View File

@@ -0,0 +1,63 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.design.Dependency;
import org.sonar.api.design.DependencyDto;
import org.sonar.api.resources.Project;

public final class DependencyPersister {

private ResourcePersister resourcePersister;
private DatabaseSession session;

public DependencyPersister(ResourcePersister resourcePersister, DatabaseSession session) {
this.resourcePersister = resourcePersister;
this.session = session;
}

public void saveDependency(Project project, Dependency dependency, Dependency parentDependency) {
Snapshot fromSnapshot = resourcePersister.saveResource(project, dependency.getFrom());
Snapshot toSnapshot = resourcePersister.saveResource(project, dependency.getTo());
Snapshot projectSnapshot = resourcePersister.saveProject(project);

DependencyDto model = new DependencyDto();
model.setProjectSnapshotId(projectSnapshot.getId());
model.setUsage(dependency.getUsage());
model.setWeight(dependency.getWeight());

model.setFromResourceId(fromSnapshot.getResourceId());
model.setFromScope(fromSnapshot.getScope());
model.setFromSnapshotId(fromSnapshot.getId());

model.setToResourceId(toSnapshot.getResourceId());
model.setToSnapshotId(toSnapshot.getId());
model.setToScope(toSnapshot.getScope());

if (parentDependency != null) {
// assume that it has been previously saved
model.setParentDependencyId(parentDependency.getId());
}
session.save(model);
dependency.setId(model.getId());
}
}

+ 65
- 0
sonar-batch/src/main/java/org/sonar/batch/index/EventPersister.java View File

@@ -0,0 +1,65 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import org.sonar.api.batch.Event;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;

import java.util.Collections;
import java.util.List;

public final class EventPersister {
private DatabaseSession session;
private ResourcePersister resourcePersister;

public EventPersister(DatabaseSession session, ResourcePersister resourcePersister) {
this.session = session;
this.resourcePersister = resourcePersister;
}

public List<Event> getEvents(Resource resource) {
Snapshot snapshot = resourcePersister.getSnapshot(resource);
if (snapshot == null) {
return Collections.emptyList();
}
return session.getResults(Event.class, "resourceId", snapshot.getResourceId());
}

public void deleteEvent(Event event) {
session.remove(event);
session.commit();
}

public void saveEvent(Project project, Resource resource, Event event) {
Snapshot snapshot = resourcePersister.saveResource(project, resource);
if (snapshot != null) {
if (event.getDate()==null) {
event.setSnapshot(snapshot);
} else {
event.setResourceId(snapshot.getResourceId());
}
session.save(event);
session.commit();
}
}
}

+ 68
- 0
sonar-batch/src/main/java/org/sonar/batch/index/LinkPersister.java View File

@@ -0,0 +1,68 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectLink;

public final class LinkPersister {
private DatabaseSession session;
private ResourcePersister resourcePersister;

public LinkPersister(DatabaseSession session, ResourcePersister resourcePersister) {
this.session = session;
this.resourcePersister = resourcePersister;
}

public void saveLink(Project project, ProjectLink link) {
Snapshot snapshot = resourcePersister.getSnapshot(project);
if (snapshot != null) {
ResourceModel projectDao = session.reattach(ResourceModel.class, snapshot.getResourceId());
ProjectLink dbLink = projectDao.getProjectLink(link.getKey());
if (dbLink == null) {
link.setResource(projectDao);
projectDao.getProjectLinks().add(link);
session.save(link);

} else {
dbLink.copyFieldsFrom(link);
session.save(dbLink);
}
session.commit();
}
}

public void deleteLink(Project project, String linkKey) {
Snapshot snapshot = resourcePersister.getSnapshot(project);
if (snapshot != null) {
ResourceModel model = session.reattach(ResourceModel.class, snapshot.getResourceId());
ProjectLink dbLink = model.getProjectLink(linkKey);
if (dbLink != null) {
session.remove(dbLink);
model.getProjectLinks().remove(dbLink);
session.commit();
}

}
}
}

+ 133
- 0
sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java View File

@@ -0,0 +1,133 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import com.google.common.collect.Sets;
import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.LoggerFactory;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.MeasureModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.RuleMeasure;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;

import java.util.Iterator;
import java.util.Set;

public final class MeasurePersister {

private boolean delayedMode = false;
private Set<MeasureModel> unsavedMeasures = Sets.newLinkedHashSet();
private DatabaseSession session;
private ResourcePersister resourcePersister;

public MeasurePersister(DatabaseSession session, ResourcePersister resourcePersister) {
this.session = session;
this.resourcePersister = resourcePersister;
}

public void setDelayedMode(boolean delayedMode) {
this.delayedMode = delayedMode;
}

public void saveMeasure(Project project, Measure measure) {
saveMeasure(project, project, measure);
}

public void saveMeasure(Project project, Resource resource, Measure measure) {
Snapshot snapshot = resourcePersister.saveResource(project, resource);
if (snapshot != null) {
if (delayedMode && measure.getPersistenceMode().useMemory()) {
MeasureModel model = createModel(measure);
model.setSnapshotId(snapshot.getId());
unsavedMeasures.add(model);

} else if (shouldPersistMeasure(resource, measure)) {
if (measure.getId() != null) {
// update
MeasureModel model = session.reattach(MeasureModel.class, measure.getId());
model = mergeModel(measure, model);
model.save(session);

} else {
// insert
MeasureModel model = createModel(measure);
model.setSnapshotId(snapshot.getId());
model.save(session);
measure.setId(model.getId()); // could be removed
}
}
}
}

static boolean shouldPersistMeasure(Resource resource, Measure measure) {
Metric metric = measure.getMetric();
return measure.getPersistenceMode().useDatabase() && !(
ResourceUtils.isEntity(resource) &&
metric.isOptimizedBestValue() == Boolean.TRUE &&
metric.getBestValue() != null &&
NumberUtils.compare(metric.getBestValue(), measure.getValue()) == 0 &&
!measure.hasOptionalData());
}

public void dump() {
LoggerFactory.getLogger(getClass()).debug("{} measures to dump", unsavedMeasures.size());
for (Iterator<MeasureModel> it = unsavedMeasures.iterator(); it.hasNext();) {
MeasureModel model = it.next();
model.save(session);
it.remove();
}
session.commit();
}

MeasureModel createModel(Measure measure) {
return mergeModel(measure, new MeasureModel());
}

MeasureModel mergeModel(Measure measure, MeasureModel merge) {
merge.setMetricId(measure.getMetric().getId());// we assume that the index has updated the metric
merge.setDescription(measure.getDescription());
merge.setData(measure.getData());
merge.setAlertStatus(measure.getAlertStatus());
merge.setAlertText(measure.getAlertText());
merge.setTendency(measure.getTendency());
merge.setDiffValue1(measure.getDiffValue1());
merge.setDiffValue2(measure.getDiffValue2());
merge.setDiffValue3(measure.getDiffValue3());
merge.setUrl(measure.getUrl());
merge.setCharacteristic(measure.getCharacteristic());
if (measure.getValue() != null) {
merge.setValue(measure.getValue().doubleValue());
} else {
merge.setValue(null);
}
if (measure instanceof RuleMeasure) {
RuleMeasure ruleMeasure = (RuleMeasure) measure;
merge.setRulesCategoryId(ruleMeasure.getRuleCategory());
merge.setRulePriority(ruleMeasure.getRulePriority());
merge.setRule(ruleMeasure.getRule());
}
return merge;
}
}

+ 61
- 0
sonar-batch/src/main/java/org/sonar/batch/index/PersistenceManager.java View File

@@ -0,0 +1,61 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import org.sonar.api.batch.Event;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.design.Dependency;
import org.sonar.api.measures.Measure;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectLink;
import org.sonar.api.resources.Resource;
import org.sonar.api.rules.Violation;

import java.util.List;

public interface PersistenceManager {
void clear();

void setDelayedMode(boolean b);

void dump();

void saveProject(Project project);

Snapshot saveResource(Project project, Resource resource);

void setSource(Project project, Resource resource, String source);

void saveMeasure(Project project, Resource resource, Measure measure);

void saveDependency(Project project, Dependency dependency, Dependency parentDependency);

void saveViolation(Project project, Violation violation);

void saveLink(Project project, ProjectLink link);

void deleteLink(Project project, String key);

List<Event> getEvents(Resource resource);

void deleteEvent(Event event);

void saveEvent(Project project, Resource resource, Event event);
}

+ 247
- 0
sonar-batch/src/main/java/org/sonar/batch/index/ResourcePersister.java View File

@@ -0,0 +1,247 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import com.google.common.collect.Maps;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Library;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
import org.sonar.api.utils.SonarException;

import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class ResourcePersister {

private DatabaseSession session;

private Map<Resource, Snapshot> snapshotsByResource = Maps.newHashMap();

public ResourcePersister(DatabaseSession session) {
this.session = session;
}

public Snapshot saveProject(Project project) {
Snapshot snapshot = snapshotsByResource.get(project);
if (snapshot == null) {
snapshot = doSaveProject(project);
}
return snapshot;
}

public Snapshot getSnapshot(Resource resource) {
if (resource != null) {
return snapshotsByResource.get(resource);
}
return null;
}

/**
* just for unit tests
*/
Map<Resource, Snapshot> getSnapshotsByResource() {
return snapshotsByResource;
}

private Snapshot doSaveProject(Project project) {
ResourceModel model = findOrCreateModel(project, project.getKey());
model.setLanguageKey(project.getLanguageKey());// ugly, only for projects

Snapshot parentSnapshot = null;
if (project.getParent() != null) {
// assume that the parent project has already been saved
parentSnapshot = snapshotsByResource.get(project.getParent());
model.setRootId((Integer) ObjectUtils.defaultIfNull(parentSnapshot.getRootProjectId(), parentSnapshot.getResourceId()));
}
model = session.save(model);
project.setId(model.getId()); // TODO to be removed

Snapshot snapshot = new Snapshot(model, parentSnapshot);
snapshot.setVersion(project.getAnalysisVersion());
snapshot.setCreatedAt(project.getAnalysisDate());
snapshot = session.save(snapshot);
session.commit();
snapshotsByResource.put(project, snapshot);
return snapshot;
}

public Snapshot saveResource(Project project, Resource resource) {
if (resource == null) {
return null;
}
Snapshot snapshot = snapshotsByResource.get(resource);
if (snapshot == null) {
if (resource instanceof Project) {
snapshot = doSaveProject((Project) resource);

} else if (resource instanceof Library) {
snapshot = doSaveLibrary(project, (Library) resource);

} else {
snapshot = doSaveResource(project, resource);
}
}
return snapshot;
}

private Snapshot doSaveLibrary(Project project, Library library) {
ResourceModel model = findOrCreateModel(library, library.getKey());
model = session.save(model);
library.setId(model.getId()); // TODO to be removed
library.setEffectiveKey(library.getKey());

Snapshot snapshot = findLibrarySnapshot(model.getId(), library.getVersion());
if (snapshot == null) {
snapshot = new Snapshot(model, null);
snapshot.setCreatedAt(project.getAnalysisDate());
snapshot.setVersion(library.getVersion());
snapshot.setStatus(Snapshot.STATUS_PROCESSED);

// see http://jira.codehaus.org/browse/SONAR-1850
// The qualifier must be LIB, even if the resource is TRK, because this snapshot has no measures.
snapshot.setQualifier(Resource.QUALIFIER_LIB);
snapshot = session.save(snapshot);
}
session.commit();
return snapshot;
}

private Snapshot findLibrarySnapshot(Integer resourceId, String version) {
Query query = session.createQuery("from " + Snapshot.class.getSimpleName() + " s WHERE s.resourceId=:resourceId AND s.version=:version AND s.scope=:scope AND s.qualifier<>:qualifier AND s.last=:last");
query.setParameter("resourceId", resourceId);
query.setParameter("version", version);
query.setParameter("scope", Resource.SCOPE_SET);
query.setParameter("qualifier", Resource.QUALIFIER_LIB);
query.setParameter("last", Boolean.TRUE);
List<Snapshot> snapshots = query.getResultList();
if (snapshots.isEmpty()) {
snapshots = session.getResults(Snapshot.class, "resourceId", resourceId, "version", version, "scope", Resource.SCOPE_SET, "qualifier", Resource.QUALIFIER_LIB);
}
return (snapshots.isEmpty() ? null : snapshots.get(0));
}

/**
* Everything except project and library
*/
private Snapshot doSaveResource(Project project, Resource resource) {
String databaseKey = getDatabaseKey(project, resource);
ResourceModel model = findOrCreateModel(resource, databaseKey);
Snapshot projectSnapshot = snapshotsByResource.get(project);
model.setRootId(projectSnapshot.getResourceId());
model = session.save(model);
resource.setId(model.getId()); // TODO to be removed
resource.setEffectiveKey(databaseKey);

Snapshot parentSnapshot = (Snapshot)ObjectUtils.defaultIfNull(getSnapshot(resource.getParent()), projectSnapshot);
Snapshot snapshot = new Snapshot(model, parentSnapshot);
snapshot = session.save(snapshot);
session.commit();
snapshotsByResource.put(resource, snapshot);
return snapshot;
}

public void clear() {
// we keep cache of projects
for (Iterator<Map.Entry<Resource, Snapshot>> it = snapshotsByResource.entrySet().iterator(); it.hasNext();) {
Map.Entry<Resource, Snapshot> entry = it.next();
if (!ResourceUtils.isSet(entry.getKey())) {
it.remove();
}
}
}


private ResourceModel findOrCreateModel(Resource resource, String databaseKey) {
ResourceModel model;
try {
model = session.getSingleResult(ResourceModel.class, "key", databaseKey);
if (model == null) {
model = createModel(resource, databaseKey);

} else {
mergeModel(model, resource);
}
return model;

} catch (NonUniqueResultException e) {
throw new SonarException("The resource '" + databaseKey + "' is duplicated in database.");
}
}

static ResourceModel createModel(Resource resource, String databaseKey) {
ResourceModel model = new ResourceModel();
model.setEnabled(Boolean.TRUE);
model.setDescription(resource.getDescription());
model.setKey(databaseKey);
if (resource.getLanguage() != null) {
model.setLanguageKey(resource.getLanguage().getKey());
}
if (StringUtils.isNotBlank(resource.getName())) {
model.setName(resource.getName());
} else {
model.setName(resource.getKey());
}
model.setLongName(resource.getLongName());
model.setScope(resource.getScope());
model.setQualifier(resource.getQualifier());
return model;
}

static void mergeModel(ResourceModel model, Resource resource) {
model.setEnabled(true);
if (StringUtils.isNotBlank(resource.getName())) {
model.setName(resource.getName());
}
if (StringUtils.isNotBlank(resource.getLongName())) {
model.setLongName(resource.getLongName());
}
if (StringUtils.isNotBlank(resource.getDescription())) {
model.setDescription(resource.getDescription());
}
if (!ResourceUtils.isLibrary(resource)) {
model.setScope(resource.getScope());
model.setQualifier(resource.getQualifier());
}
if (resource.getLanguage() != null) {
model.setLanguageKey(resource.getLanguage().getKey());
}
}

static String getDatabaseKey(Project project, Resource resource) {
if (StringUtils.equals(Resource.SCOPE_SET, resource.getScope())) {
// projects + libraries
return resource.getKey();
}
return new StringBuilder(ResourceModel.KEY_SIZE)
.append(project.getKey())
.append(':')
.append(resource.getKey())
.toString();
}
}

+ 59
- 0
sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java View File

@@ -0,0 +1,59 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import com.google.common.collect.Sets;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.database.model.SnapshotSource;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.utils.SonarException;

import java.util.Set;

public final class SourcePersister {

private DatabaseSession session;
private Set<Integer> savedSnapshotIds = Sets.newHashSet();
private ResourcePersister resourcePersister;

public SourcePersister(DatabaseSession session, ResourcePersister resourcePersister) {
this.session = session;
this.resourcePersister = resourcePersister;
}

public void saveSource(Project project, Resource resource, String source) {
Snapshot snapshot = resourcePersister.saveResource(project, resource);
if (snapshot != null) {

if (savedSnapshotIds.contains(snapshot.getId())) {
throw new SonarException("Can not set twice the source of " + resource);
}
session.save(new SnapshotSource(snapshot.getId(), source));
session.commit();
savedSnapshotIds.add(snapshot.getId());
}
}

public void clear() {
savedSnapshotIds.clear();
}
}

+ 79
- 0
sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java View File

@@ -0,0 +1,79 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import com.google.common.collect.Maps;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.RuleFailureModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Project;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.Violation;
import org.sonar.api.utils.SonarException;

import java.util.Map;

public final class ViolationPersister {

private DatabaseSession session;
private ResourcePersister resourcePersister;
private Map<Rule, Integer> ruleIds = Maps.newHashMap();

public ViolationPersister(DatabaseSession session, ResourcePersister resourcePersister) {
this.session = session;
this.resourcePersister = resourcePersister;
}

public void saveViolation(Project project, Violation violation) {
Snapshot snapshot = resourcePersister.saveResource(project, violation.getResource());
if (snapshot != null) {
session.save(toModel(snapshot, violation));
}
}

private RuleFailureModel toModel(Snapshot snapshot, Violation violation) {
RuleFailureModel model = new RuleFailureModel();
model.setRuleId(getRuleId(violation.getRule()));
model.setPriority(violation.getPriority());
model.setLine(violation.getLineId());
model.setMessage(violation.getMessage());
model.setCost(violation.getCost());
model.setSnapshotId(snapshot.getId());
return model;
}

private Integer getRuleId(Rule rule) {
Integer ruleId = ruleIds.get(rule);
if (ruleId == null) {
Rule persistedRule = session.getSingleResult(Rule.class, "pluginName", rule.getRepositoryKey(), "key", rule.getKey(), "enabled", true);
if (persistedRule == null) {
throw new SonarException("Rule not found: " + rule);
}
ruleId = persistedRule.getId();
ruleIds.put(rule, ruleId);

}
return ruleId;
}

public void clear() {
ruleIds.clear();
}
}

+ 0
- 52
sonar-batch/src/main/java/org/sonar/batch/indexer/DefaultPersister.java View File

@@ -1,52 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.indexer;

import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.database.model.Snapshot;

public class DefaultPersister extends ResourcePersister {

public DefaultPersister(DatabaseSession session) {
super(session);
}

@Override
protected Snapshot createSnapshot(Bucket bucket, ResourceModel resourceModel) {
Snapshot parentSnapshot = (bucket.getParent() != null ? bucket.getParent().getSnapshot() : null);
Snapshot snapshot = new Snapshot(resourceModel, parentSnapshot);
return snapshot;
}

@Override
protected void prepareResourceModel(ResourceModel resourceModel, Bucket bucket) {
resourceModel.setRootId(bucket.getProject() != null ? bucket.getProject().getResourceId() : null);
}

@Override
protected String generateEffectiveKey(Bucket bucket) {
return new StringBuilder(ResourceModel.KEY_SIZE)
.append(bucket.getProject().getResource().getKey())
.append(':')
.append(bucket.getResource().getKey())
.toString();
}
}

+ 0
- 470
sonar-batch/src/main/java/org/sonar/batch/indexer/DefaultSonarIndex.java View File

@@ -1,470 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.indexer;

import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.Event;
import org.sonar.api.batch.SonarIndex;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.MeasureModel;
import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.database.model.SnapshotSource;
import org.sonar.api.design.Dependency;
import org.sonar.api.design.DependencyDto;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilter;
import org.sonar.api.measures.MeasuresFilters;
import org.sonar.api.measures.Metric;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.ProjectLink;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
import org.sonar.api.rules.Violation;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.*;
import org.sonar.jpa.dao.MeasuresDao;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import java.util.*;

public class DefaultSonarIndex extends SonarIndex {

private static final Logger LOG = LoggerFactory.getLogger(DefaultSonarIndex.class);

private DatabaseSession session;
private ResourcePersisters resourcePersisters;
private Bucket<Project> rootProjectBucket;
private Bucket<Project> selectedProjectBucket;
private DefaultResourceCreationLock lock;

private ViolationFilters violationFilters;
private ResourceFilters resourceFilters;

// data
private Map<Resource, Bucket> buckets = Maps.newHashMap();
private Set<Dependency> dependencies = Sets.newHashSet();
private Map<Resource, Map<Resource, Dependency>> outgoingDependenciesByResource = new HashMap<Resource, Map<Resource, Dependency>>();
private Map<Resource, Map<Resource, Dependency>> incomingDependenciesByResource = new HashMap<Resource, Map<Resource, Dependency>>();

// dao
private ViolationsDao violationsDao;
private MeasuresDao measuresDao;
private ProjectTree projectTree;

public DefaultSonarIndex(DatabaseSession session, ProjectTree projectTree, DefaultResourceCreationLock lock) {
this.session = session;
this.projectTree = projectTree;
this.resourcePersisters = new ResourcePersisters(session);
this.lock = lock;
}

public void start() {
Project rootProject = projectTree.getRootProject();

this.rootProjectBucket = new Bucket<Project>(rootProject);
persist(rootProjectBucket);
this.buckets.put(rootProject, rootProjectBucket);
this.selectedProjectBucket = rootProjectBucket;

for (Project project : rootProject.getModules()) {
addProject(project);
}
session.commit();
}

private void addProject(Project project) {
addResource(project);
for (Project module : project.getModules()) {
addProject(module);
}
}

public void selectProject(Project project, ResourceFilters resourceFilters, ViolationFilters violationFilters, MeasuresDao measuresDao, ViolationsDao violationsDao) {
this.selectedProjectBucket = buckets.get(project);
this.resourceFilters = resourceFilters;
this.violationFilters = violationFilters;
this.violationsDao = violationsDao;
this.measuresDao = measuresDao;
}

/**
* Keep only project stuff
*/
public void clear() {
Iterator<Map.Entry<Resource, Bucket>> it = buckets.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Resource, Bucket> entry = it.next();
Resource resource = entry.getKey();
if ( !ResourceUtils.isSet(resource)) {
entry.getValue().clear();
it.remove();
}
}

Set<Dependency> projectDependencies = getDependenciesBetweenProjects();
dependencies.clear();
incomingDependenciesByResource.clear();
outgoingDependenciesByResource.clear();
for (Dependency projectDependency : projectDependencies) {
projectDependency.setId(null);
registerDependency(projectDependency);
}

lock.unlock();
}

/* ------------ RESOURCES */
public Project getRootProject() {
return rootProjectBucket.getResource();
}

public Project getProject() {
return selectedProjectBucket.getResource();
}

public Bucket getBucket(Resource resource) {
return buckets.get(resource);
}

public Resource getResource(Resource resource) {
Bucket bucket = buckets.get(resource);
if (bucket != null) {
return bucket.getResource();
}
return null;
}

public List<Resource> getChildren(Resource resource) {
List<Resource> children = Lists.newArrayList();
Bucket<?> bucket = buckets.get(resource);
if (bucket != null) {
for (Bucket childBucket : bucket.getChildren()) {
children.add(childBucket.getResource());
}
}
return children;
}

public Resource addResource(Resource resource) {
return getOrCreateBucket(resource, false).getResource();
}

private Bucket<Resource> getOrCreateBucket(Resource resource, boolean mustExist) {
Bucket bucket = buckets.get(resource);
if (bucket != null) {
return bucket;
}

if (mustExist && lock.isLocked() && !ResourceUtils.isLibrary(resource)) {
LOG.warn("The following resource has not been registered before saving violation/measure/event: " + resource);
}

prepareResource(resource);
bucket = new Bucket<Resource>(resource);
buckets.put(resource, bucket);

Bucket parentBucket = null;
Resource parent = resource.getParent();
if (parent != null) {
parentBucket = getOrCreateBucket(parent, mustExist);
} else if ( !ResourceUtils.isLibrary(resource)) {
parentBucket = selectedProjectBucket;
}
bucket.setParent(parentBucket);
bucket.setProject(selectedProjectBucket);

persist(bucket);
return bucket;
}

private void prepareResource(Resource resource) {
resource.setExcluded(resourceFilters != null && resourceFilters.isExcluded(resource));
}

private void persist(Bucket bucket) {
resourcePersisters.get(bucket).persist(bucket);
}

/* ------------ MEASURES */
public Measure getMeasure(Resource resource, Metric metric) {
return getOrCreateBucket(resource, false).getMeasures(MeasuresFilters.metric(metric));
}

public <M> M getMeasures(Resource resource, MeasuresFilter<M> filter) {
return getOrCreateBucket(resource, false).getMeasures(filter);
}

/* ------------ SOURCE CODE */

public void setSource(Resource resource, String source) {
Bucket bucket = getOrCreateBucket(resource, false);

if ( !bucket.isExcluded()) {
if (bucket.isSourceSaved()) {
LOG.warn("Trying to save twice the source of " + resource);

} else {
try {
session.save(new SnapshotSource(bucket.getSnapshotId(), source));
} catch (Exception e) {
throw new SonarException("Unable to save source [resource=" + resource + ",snapshotId=" + bucket.getSnapshotId() + "]", e);
}
bucket.setSourceSaved(true);
}
}
}

/* ------------ RULE VIOLATIONS */

public void addViolation(Violation violation) {
Bucket bucket;
Resource resource = violation.getResource();
if (resource == null) {
bucket = selectedProjectBucket;
} else {
bucket = getOrCreateBucket(resource, true);
}
if ( !bucket.isExcluded()) {
persistViolation(violation, bucket.getSnapshot());
}
}

private void persistViolation(Violation violation, Snapshot snapshot) {
boolean isIgnored = violationFilters != null && violationFilters.isIgnored(violation);
if ( !isIgnored) {
violationsDao.saveViolation(snapshot, violation);
}
}

/* ------------ MEASURES */
public Measure saveMeasure(Resource resource, Measure measure) {
if (measure.getId() == null) {
return addMeasure(resource, measure);
}
return updateMeasure(measure);
}

public Measure addMeasure(Resource resource, Measure measure) {
Bucket bucket = getOrCreateBucket(resource, true);
if ( !bucket.isExcluded()) {
if (bucket.getMeasures(MeasuresFilters.measure(measure)) != null) {
throw new IllegalArgumentException("This measure has already been saved: " + measure + ",resource: " + resource);
}
if (shouldPersistMeasure(resource, measure)) {
persistMeasure(bucket, measure);
}

if (measure.getPersistenceMode().useMemory()) {
bucket.addMeasure(measure);
}
}
return measure;
}

public Measure updateMeasure(Measure measure) {
if (measure.getId() == null) {
throw new IllegalStateException("Measure can not be updated because it has never been saved");
}

MeasureModel model = session.reattach(MeasureModel.class, measure.getId());
model = MeasureModel.build(measure, model);
model.setMetric(measuresDao.getMetric(measure.getMetric()));
model.save(session);
return measure;
}

private void persistMeasure(Bucket bucket, Measure measure) {
Metric metric = measuresDao.getMetric(measure.getMetric());
MeasureModel measureModel = MeasureModel.build(measure);
measureModel.setMetric(metric); // hibernate synchronized metric
measureModel.setSnapshotId(bucket.getSnapshotId());
measureModel.save(session);

// the id is saved for future updates
measure.setId(measureModel.getId());
}

private boolean shouldPersistMeasure(Resource resource, Measure measure) {
Metric metric = measure.getMetric();
return measure.getPersistenceMode().useDatabase() && !(
ResourceUtils.isEntity(resource) &&
metric.isOptimizedBestValue() == Boolean.TRUE &&
metric.getBestValue() != null &&
NumberUtils.compare(metric.getBestValue(), measure.getValue()) == 0 &&
!measure.hasOptionalData());
}

/* --------------- DEPENDENCIES */
public Dependency saveDependency(Dependency dependency) {
Dependency persistedDep = getEdge(dependency.getFrom(), dependency.getTo());
if (persistedDep != null && persistedDep.getId() != null) {
return persistedDep;
}
Bucket from = getOrCreateBucket(dependency.getFrom(), true);
Bucket to = getOrCreateBucket(dependency.getTo(), true);

DependencyDto dto = new DependencyDto();
dto.setFromResourceId(from.getResourceId());
dto.setFromScope(from.getResource().getScope());
dto.setFromSnapshotId(from.getSnapshotId());
dto.setToResourceId(to.getResourceId());
dto.setToSnapshotId(to.getSnapshotId());
dto.setToScope(to.getResource().getScope());
dto.setProjectSnapshotId(selectedProjectBucket.getSnapshotId());
dto.setUsage(dependency.getUsage());
dto.setWeight(dependency.getWeight());

Dependency parentDependency = dependency.getParent();
if (parentDependency != null) {
saveDependency(parentDependency);
dto.setParentDependencyId(parentDependency.getId());
}
session.save(dto);
dependency.setId(dto.getId());
registerDependency(dependency);

return dependency;
}

protected void registerDependency(Dependency dependency) {
dependencies.add(dependency);
registerOutgoingDependency(dependency);
registerIncomingDependency(dependency);
}

private void registerOutgoingDependency(Dependency dependency) {
Map<Resource, Dependency> outgoingDeps = outgoingDependenciesByResource.get(dependency.getFrom());
if (outgoingDeps == null) {
outgoingDeps = new HashMap<Resource, Dependency>();
outgoingDependenciesByResource.put(dependency.getFrom(), outgoingDeps);
}
outgoingDeps.put(dependency.getTo(), dependency);
}

private void registerIncomingDependency(Dependency dependency) {
Map<Resource, Dependency> incomingDeps = incomingDependenciesByResource.get(dependency.getTo());
if (incomingDeps == null) {
incomingDeps = new HashMap<Resource, Dependency>();
incomingDependenciesByResource.put(dependency.getTo(), incomingDeps);
}
incomingDeps.put(dependency.getFrom(), dependency);
}

public Set<Dependency> getDependencies() {
return dependencies;
}

/* ------------ LINKS */

public void saveLink(ProjectLink link) {
ResourceModel projectDao = session.reattach(ResourceModel.class, selectedProjectBucket.getResourceId());
ProjectLink dbLink = projectDao.getProjectLink(link.getKey());
if (dbLink == null) {
link.setResource(projectDao);
projectDao.getProjectLinks().add(link);
session.save(link);

} else {
dbLink.copyFieldsFrom(link);
session.save(dbLink);
}
}

public void deleteLink(String key) {
ResourceModel projectDao = session.reattach(ResourceModel.class, selectedProjectBucket.getResourceId());
ProjectLink dbLink = projectDao.getProjectLink(key);
if (dbLink != null) {
session.remove(dbLink);
projectDao.getProjectLinks().remove(dbLink);
}
}

/* ----------- EVENTS */
public List<Event> getEvents(Resource resource) {
Bucket bucket = getOrCreateBucket(resource, true);
return session.getResults(Event.class, "resourceId", bucket.getResourceId());
}

public void deleteEvent(Event event) {
session.remove(event);
}

public Event createEvent(Resource resource, String name, String description, String category, Date date) {
Bucket bucket = getOrCreateBucket(resource, true);
Event event;
if (date == null) {
event = new Event(name, description, category, bucket.getSnapshot());
} else {
event = new Event(name, description, category, date, bucket.getResourceId());
}
return session.save(event);
}

public Dependency getEdge(Resource from, Resource to) {
Map<Resource, Dependency> map = outgoingDependenciesByResource.get(from);
if (map != null) {
return map.get(to);
}
return null;
}

public boolean hasEdge(Resource from, Resource to) {
return getEdge(from, to) != null;
}

public Set<Resource> getVertices() {
return buckets.keySet();
}

public Collection<Dependency> getOutgoingEdges(Resource from) {
Map<Resource, Dependency> deps = outgoingDependenciesByResource.get(from);
if (deps != null) {
return deps.values();
}
return Collections.emptyList();
}

public Collection<Dependency> getIncomingEdges(Resource to) {
Map<Resource, Dependency> deps = incomingDependenciesByResource.get(to);
if (deps != null) {
return deps.values();
}
return Collections.emptyList();
}

public Set<Dependency> getDependenciesBetweenProjects() {
Set<Dependency> result = new HashSet<Dependency>();
for (Project project : projectTree.getProjects()) {
Collection<Dependency> deps = getOutgoingDependencies(project);
for (Dependency dep : deps) {
if (ResourceUtils.isSet(dep.getTo())) {
result.add(dep);
}
}
}
return result;
}
}

+ 0
- 100
sonar-batch/src/main/java/org/sonar/batch/indexer/LibraryPersister.java View File

@@ -1,100 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.indexer;

import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Library;
import org.sonar.api.resources.Resource;

import javax.persistence.Query;
import java.util.Date;
import java.util.List;

public class LibraryPersister extends ResourcePersister<Library> {

private Date now;

public LibraryPersister(DatabaseSession session) {
super(session);
this.now = new Date();
}

LibraryPersister(DatabaseSession session, Date now) {
super(session);
this.now = now;
}

@Override
protected String generateEffectiveKey(Bucket<Library> bucket) {
return bucket.getResource().getKey();
}

@Override
protected void prepareResourceModel(ResourceModel resourceModel, Bucket<Library> bucket) {
}

@Override
protected Snapshot createSnapshot(Bucket<Library> bucket, ResourceModel resourceModel) {
Snapshot snapshot = findProject(resourceModel.getId(), bucket.getResource().getVersion());
if (snapshot == null) {
snapshot = findLibrary(resourceModel.getId(), bucket.getResource().getVersion());
}

if (snapshot == null) {
snapshot = new Snapshot(resourceModel, null);
snapshot.setCreatedAt(now);
snapshot.setVersion(bucket.getResource().getVersion());
snapshot.setStatus(Snapshot.STATUS_PROCESSED);

// see http://jira.codehaus.org/browse/SONAR-1850
// The qualifier must be LIB, even if the resource is TRK, because this snapshot has no measures.
snapshot.setQualifier(Resource.QUALIFIER_LIB);
}
return snapshot;
}

private Snapshot findLibrary(Integer resourceId, String version) {
List<Snapshot> snapshots = getSession().getResults(Snapshot.class,
"resourceId", resourceId,
"version", version,
"scope", Resource.SCOPE_SET,
"qualifier", Resource.QUALIFIER_LIB);
if (snapshots.isEmpty()) {
return null;
}
return snapshots.get(0);
}

private Snapshot findProject(Integer resourceId, String version) {
Query query = getSession().createQuery("from " + Snapshot.class.getSimpleName() + " s WHERE s.resourceId=:resourceId AND s.version=:version AND s.scope=:scope AND s.qualifier<>:qualifier AND s.last=:last");
query.setParameter("resourceId", resourceId);
query.setParameter("version", version);
query.setParameter("scope", Resource.SCOPE_SET);
query.setParameter("qualifier", Resource.QUALIFIER_LIB);
query.setParameter("last", Boolean.TRUE);
List<Snapshot> snapshots = query.getResultList();
if (snapshots.isEmpty()) {
return null;
}
return snapshots.get(0);
}
}

+ 0
- 58
sonar-batch/src/main/java/org/sonar/batch/indexer/ProjectPersister.java View File

@@ -1,58 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.indexer;

import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Project;

public class ProjectPersister extends ResourcePersister<Project> {

public ProjectPersister(DatabaseSession session) {
super(session);
}

@Override
protected String generateEffectiveKey(Bucket<Project> bucket) {
return bucket.getResource().getKey();
}

@Override
protected void prepareResourceModel(ResourceModel resourceModel, Bucket<Project> bucket) {
if (bucket.getProject() != null) {
resourceModel.setRootId(bucket.getProject().getResourceId());
}

// LIMITATION : project.getLanguage() is set only in ProjectBatch, not in AggregatorBatch, so we
// have to explicitely use project.getLanguageKey()
resourceModel.setLanguageKey(bucket.getResource().getLanguageKey());
}

@Override
protected Snapshot createSnapshot(Bucket<Project> bucket, ResourceModel resourceModel) {
Project project = bucket.getResource();
Snapshot parentSnapshot = (bucket.getParent() != null ? bucket.getParent().getSnapshot() : null);
Snapshot snapshot = new Snapshot(resourceModel, parentSnapshot);
snapshot.setVersion(project.getAnalysisVersion());
snapshot.setCreatedAt(project.getAnalysisDate());
return snapshot;
}
}

+ 0
- 96
sonar-batch/src/main/java/org/sonar/batch/indexer/ResourcePersister.java View File

@@ -1,96 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.indexer;

import javax.persistence.NonUniqueResultException;

import org.apache.commons.lang.StringUtils;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
import org.sonar.api.utils.SonarException;

public abstract class ResourcePersister<RESOURCE extends Resource> {

private DatabaseSession session;

public ResourcePersister(DatabaseSession session) {
this.session = session;
}

protected DatabaseSession getSession() {
return session;
}

public final void persist(Bucket<RESOURCE> bucket) {
String effectiveKey = generateEffectiveKey(bucket);
ResourceModel model;
try {
model = session.getSingleResult(ResourceModel.class, "key", effectiveKey);
} catch (NonUniqueResultException e) {
throw new SonarException("The resource '" + effectiveKey + "' is duplicated in the Sonar DB.");
}

RESOURCE resource = bucket.getResource();
if (model == null) {
model = ResourceModel.build(resource);
model.setKey(effectiveKey);

} else {
// update existing record
model.setEnabled(true);
if (StringUtils.isNotBlank(resource.getName())) {
model.setName(resource.getName());
}
if (StringUtils.isNotBlank(resource.getLongName())) {
model.setLongName(resource.getLongName());
}
if (StringUtils.isNotBlank(resource.getDescription())) {
model.setDescription(resource.getDescription());
}
if ( !ResourceUtils.isLibrary(resource)) {
model.setScope(resource.getScope());
model.setQualifier(resource.getQualifier());
}
if (resource.getLanguage() != null) {
model.setLanguageKey(resource.getLanguage().getKey());
}
}

prepareResourceModel(model, bucket);
model = session.save(model);
resource.setId(model.getId());
resource.setEffectiveKey(model.getKey());

Snapshot snapshot = createSnapshot(bucket, model);
if (snapshot.getId() == null) {
session.save(snapshot);
}
bucket.setSnapshot(snapshot);
}

protected abstract void prepareResourceModel(ResourceModel resourceModel, Bucket<RESOURCE> bucket);

protected abstract Snapshot createSnapshot(Bucket<RESOURCE> bucket, ResourceModel resourceModel);

protected abstract String generateEffectiveKey(Bucket<RESOURCE> bucket);
}

+ 0
- 50
sonar-batch/src/main/java/org/sonar/batch/indexer/ResourcePersisters.java View File

@@ -1,50 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.indexer;

import org.sonar.api.database.DatabaseSession;
import org.sonar.api.resources.Library;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;

import java.util.HashMap;
import java.util.Map;

public final class ResourcePersisters {

private Map<Class<? extends Resource>, ResourcePersister> persistersByClass;
private ResourcePersister defaultPersister;

public ResourcePersisters(DatabaseSession session) {
defaultPersister = new DefaultPersister(session);
persistersByClass = new HashMap<Class<? extends Resource>, ResourcePersister>();
persistersByClass.put(Project.class, new ProjectPersister(session));
persistersByClass.put(Library.class, new LibraryPersister(session));
}

public ResourcePersister get(Bucket bucket) {
return get(bucket.getResource());
}

public ResourcePersister get(Resource resource) {
ResourcePersister persister = persistersByClass.get(resource.getClass());
return persister != null ? persister : defaultPersister;
}
}

sonar-batch/src/main/java/org/sonar/batch/DecoratorsExecutor.java → sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java View File

@@ -17,41 +17,41 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.batch.phases;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchComponent;
import org.sonar.api.batch.BatchExtensionDictionnary;
import org.sonar.api.batch.Decorator;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.batch.indexer.DefaultSonarIndex;
import org.sonar.batch.DecoratorsSelector;
import org.sonar.batch.DefaultDecoratorContext;
import org.sonar.batch.index.DefaultIndex;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class DecoratorsExecutor implements CoreJob {
public class DecoratorsExecutor implements BatchComponent {

private DecoratorsSelector decoratorsSelector;
private DatabaseSession session;
private ViolationsDao violationsDao;
private static final Logger LOG = LoggerFactory.getLogger(DecoratorsExecutor.class);
private DefaultSonarIndex index;
private DefaultIndex index;

public DecoratorsExecutor(BatchExtensionDictionnary extensionDictionnary, DefaultSonarIndex index, DatabaseSession session, ViolationsDao violationsDao) {
public DecoratorsExecutor(BatchExtensionDictionnary extensionDictionnary, DefaultIndex index, DatabaseSession session) {
this.decoratorsSelector = new DecoratorsSelector(extensionDictionnary);
this.session = session;
this.violationsDao = violationsDao;
this.index = index;
}


public void execute(Project project, SensorContext sensorContext) {
public void execute(Project project) {
LoggerFactory.getLogger(DecoratorsExecutor.class).info("Execute decorators...");
Collection<Decorator> decorators = decoratorsSelector.select(project);

@@ -60,6 +60,7 @@ public class DecoratorsExecutor implements CoreJob {
}

decorateResource(project, decorators, true);
session.commit();
}

private DecoratorContext decorateResource(Resource resource, Collection<Decorator> decorators, boolean executeDecorators) {
@@ -70,7 +71,7 @@ public class DecoratorsExecutor implements CoreJob {
childrenContexts.add(childContext.setReadOnly(true));
}

DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts, session, violationsDao);
DefaultDecoratorContext context = new DefaultDecoratorContext(resource, index, childrenContexts, session);
if (executeDecorators) {
for (Decorator decorator : decorators) {
decorator.decorate(resource, context);

sonar-batch/src/main/java/org/sonar/batch/MavenPhaseExecutor.java → sonar-batch/src/main/java/org/sonar/batch/phases/MavenPhaseExecutor.java View File

@@ -17,13 +17,14 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.batch.phases;

import org.apache.commons.lang.StringUtils;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.BatchComponent;
import org.sonar.api.resources.Project;
import org.sonar.batch.MavenPluginExecutor;

public class MavenPhaseExecutor implements CoreJob {
public class MavenPhaseExecutor implements BatchComponent {

public static final String PROP_PHASE = "sonar.phase";

@@ -33,7 +34,7 @@ public class MavenPhaseExecutor implements CoreJob {
this.executor = executor;
}

public void execute(Project project, SensorContext context) {
public void execute(Project project) {
String mavenPhase = (String) project.getProperty(PROP_PHASE);
if (!StringUtils.isBlank(mavenPhase)) {
executor.execute(project, mavenPhase);

sonar-batch/src/main/java/org/sonar/batch/MavenPluginsConfigurator.java → sonar-batch/src/main/java/org/sonar/batch/phases/MavenPluginsConfigurator.java View File

@@ -17,14 +17,14 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.batch.phases;

import org.apache.commons.io.IOUtils;
import org.apache.maven.project.MavenProject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchComponent;
import org.sonar.api.batch.BatchExtensionDictionnary;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.maven.MavenPlugin;
import org.sonar.api.batch.maven.MavenPluginHandler;
import org.sonar.api.resources.Project;
@@ -34,7 +34,7 @@ import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class MavenPluginsConfigurator implements CoreJob {
public class MavenPluginsConfigurator implements BatchComponent {

private BatchExtensionDictionnary dictionnary = null;

@@ -42,7 +42,7 @@ public class MavenPluginsConfigurator implements CoreJob {
this.dictionnary = dictionnary;
}

public void execute(Project project, SensorContext context) {
public void execute(Project project) {
Logger logger = LoggerFactory.getLogger(getClass());
logger.info("Configure maven plugins...");


+ 88
- 0
sonar-batch/src/main/java/org/sonar/batch/phases/Phases.java View File

@@ -0,0 +1,88 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.phases;

import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.Project;
import org.sonar.batch.index.DefaultIndex;
import org.sonar.batch.index.PersistenceManager;

import java.util.Arrays;
import java.util.Collection;

public final class Phases {

public static Collection<Class> getPhaseClasses() {
return Arrays.<Class>asList(
DecoratorsExecutor.class, MavenPhaseExecutor.class, MavenPluginsConfigurator.class,
PostJobsExecutor.class, SensorsExecutor.class, UpdateStatusJob.class
);
}

private DecoratorsExecutor decoratorsExecutor;
private MavenPhaseExecutor mavenPhaseExecutor;
private MavenPluginsConfigurator mavenPluginsConfigurator;
private PostJobsExecutor postJobsExecutor;
private SensorsExecutor sensorsExecutor;
private UpdateStatusJob updateStatusJob;
private PersistenceManager persistenceManager;
private SensorContext sensorContext;
private DefaultIndex index;

public Phases(DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor,
MavenPluginsConfigurator mavenPluginsConfigurator,
PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, UpdateStatusJob updateStatusJob,
PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index) {
this.decoratorsExecutor = decoratorsExecutor;
this.mavenPhaseExecutor = mavenPhaseExecutor;
this.mavenPluginsConfigurator = mavenPluginsConfigurator;
this.postJobsExecutor = postJobsExecutor;
this.sensorsExecutor = sensorsExecutor;
this.updateStatusJob = updateStatusJob;
this.persistenceManager = persistenceManager;
this.sensorContext = sensorContext;
this.index = index;
}

/**
* Executed on each module
*/
public void execute(Project project) {
mavenPluginsConfigurator.execute(project);
mavenPhaseExecutor.execute(project);

persistenceManager.setDelayedMode(true);
sensorsExecutor.execute(project, sensorContext);
decoratorsExecutor.execute(project);
persistenceManager.dump();
persistenceManager.setDelayedMode(false);

if (project.isRoot()) {
updateStatusJob.execute();
postJobsExecutor.execute(project, sensorContext);
}
cleanMemory();
}

private void cleanMemory() {
persistenceManager.clear();
index.clear();
}
}

sonar-batch/src/main/java/org/sonar/batch/PostJobsExecutor.java → sonar-batch/src/main/java/org/sonar/batch/phases/PostJobsExecutor.java View File

@@ -17,21 +17,23 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.batch.phases;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchComponent;
import org.sonar.api.batch.BatchExtensionDictionnary;
import org.sonar.api.batch.PostJob;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.maven.DependsUponMavenPlugin;
import org.sonar.api.batch.maven.MavenPluginHandler;
import org.sonar.api.resources.Project;
import org.sonar.batch.MavenPluginExecutor;

import java.util.Collection;

public class PostJobsExecutor implements CoreJob {
public class PostJobsExecutor implements BatchComponent {
private static final Logger LOG = LoggerFactory.getLogger(PostJobsExecutor.class);

private Collection<PostJob> postJobs;
@@ -48,14 +50,12 @@ public class PostJobsExecutor implements CoreJob {
}

public void execute(Project project, SensorContext context) {
if (shouldExecuteOn(project)) {
logPostJobs();
logPostJobs();

for (PostJob postJob : postJobs) {
LOG.info("Executing post-job {}", postJob.getClass());
executeMavenPlugin(project, postJob);
postJob.executeOn(project, context);
}
for (PostJob postJob : postJobs) {
LOG.info("Executing post-job {}", postJob.getClass());
executeMavenPlugin(project, postJob);
postJob.executeOn(project, context);
}
}

@@ -65,11 +65,6 @@ public class PostJobsExecutor implements CoreJob {
}
}

private boolean shouldExecuteOn(Project project) {
return postJobs != null && project.isRoot();
}


private void executeMavenPlugin(Project project, PostJob job) {
if (job instanceof DependsUponMavenPlugin) {
MavenPluginHandler handler = ((DependsUponMavenPlugin) job).getMavenPluginHandler(project);

sonar-batch/src/main/java/org/sonar/batch/SensorsExecutor.java → sonar-batch/src/main/java/org/sonar/batch/phases/SensorsExecutor.java View File

@@ -17,11 +17,12 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.batch.phases;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchComponent;
import org.sonar.api.batch.BatchExtensionDictionnary;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
@@ -30,12 +31,13 @@ import org.sonar.api.batch.maven.MavenPluginHandler;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.TimeProfiler;
import org.sonar.batch.MavenPluginExecutor;

import java.util.Collection;

public class SensorsExecutor implements CoreJob {
public class SensorsExecutor implements BatchComponent {
private static final Logger logger = LoggerFactory.getLogger(SensorsExecutor.class);
private Collection<Sensor> sensors;
private DatabaseSession session;
private MavenPluginExecutor mavenExecutor;
@@ -54,7 +56,7 @@ public class SensorsExecutor implements CoreJob {
for (Sensor sensor : sensors) {
executeMavenPlugin(project, sensor);

TimeProfiler profiler = new TimeProfiler(logger).start("Sensor "+ sensor);
TimeProfiler profiler = new TimeProfiler(logger).start("Sensor " + sensor);
sensor.analyse(project, context);
session.commit();
profiler.stop();

sonar-batch/src/main/java/org/sonar/batch/FinalizeSnapshotsJob.java → sonar-batch/src/main/java/org/sonar/batch/phases/UpdateStatusJob.java View File

@@ -17,37 +17,31 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.batch.phases;

import org.slf4j.LoggerFactory;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.BatchComponent;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Project;
import org.sonar.batch.ServerMetadata;

import javax.persistence.Query;

public class FinalizeSnapshotsJob implements CoreJob {
public class UpdateStatusJob implements BatchComponent {

private DatabaseSession session;
private ServerMetadata server;
private Snapshot snapshot;
private Snapshot snapshot; // TODO remove this component

public FinalizeSnapshotsJob(ServerMetadata server, DatabaseSession session, Snapshot snapshot) {
public UpdateStatusJob(ServerMetadata server, DatabaseSession session, Snapshot snapshot) {
this.session = session;
this.server = server;
this.snapshot = snapshot;
}

public void execute(Project project, SensorContext context) {
if (shouldExecuteOn(project)) {
Snapshot previousLastSnapshot = getPreviousLastSnapshot(snapshot);
updateFlags(snapshot, previousLastSnapshot);
}
}

private boolean shouldExecuteOn(Project project) {
return project.isRoot();
public void execute() {
Snapshot previousLastSnapshot = getPreviousLastSnapshot(snapshot);
updateFlags(snapshot, previousLastSnapshot);
}

private Snapshot getPreviousLastSnapshot(Snapshot snapshot) {

+ 0
- 29
sonar-batch/src/test/java/org/sonar/batch/CoreJobsTest.java View File

@@ -1,29 +0,0 @@
package org.sonar.batch;

import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.assertThat;
import org.junit.Test;

import java.util.List;

public class CoreJobsTest {

@Test
public void mavenPluginsAreExecutedAfterBeingConfigured() {
List<Class<? extends CoreJob>> jobs = CoreJobs.allJobs();
assertThat(jobs.indexOf(FinalizeSnapshotsJob.class),
greaterThan(jobs.indexOf(DecoratorsExecutor.class)));
}

@Test
public void finalizeJobIsExecutedAfterDecorators() {
List<Class<? extends CoreJob>> jobs = CoreJobs.allJobs();
assertThat(jobs.indexOf(FinalizeSnapshotsJob.class),
greaterThan(jobs.indexOf(DecoratorsExecutor.class)));
}

@Test
public void allJobs() {
assertThat(CoreJobs.allJobs().size(), greaterThan(3));
}
}

+ 113
- 113
sonar-batch/src/test/java/org/sonar/batch/DefaultTimeMachineTest.java View File

@@ -1,113 +1,113 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
import org.junit.Test;
import org.sonar.api.batch.TimeMachineQuery;
import org.sonar.jpa.dao.MeasuresDao;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.batch.indexer.DefaultSonarIndex;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.number.OrderingComparisons.greaterThan;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class DefaultTimeMachineTest extends AbstractDbUnitTestCase {
@Test(timeout = 3000)
public void loadMeasureFieldsFromDate() throws ParseException {
setupData("loadMeasuresFromDate");
DefaultTimeMachine timeMachine = initTimeMachine();
TimeMachineQuery query = new TimeMachineQuery(newProject()).setFrom(date("2008-02-01")).setMetrics(Arrays.asList(CoreMetrics.NCLOC));
List<Object[]> measures = timeMachine.getMeasuresFields(query);
assertThat(measures.size(), is(3));
for (Object[] measure : measures) {
assertThat(measure.length, is(3)); // 3 fields
assertThat(measure[1], is((Object) CoreMetrics.NCLOC));
}
assertThat(measures.get(0)[2], is((Object) 200d));
assertThat(measures.get(1)[2], is((Object) 230d));
assertThat(measures.get(2)[2], is((Object) 180d));
}
private DefaultTimeMachine initTimeMachine() {
DefaultSonarIndex index = mock(DefaultSonarIndex.class);
DefaultTimeMachine timeMachine = new DefaultTimeMachine(getSession(), index, new MeasuresDao(getSession()));
return timeMachine;
}
private Project newProject() {
Project project = new Project("group:artifact");
project.setId(1);
return project;
}
@Test(timeout = 3000)
public void loadMeasuresFromDate() throws ParseException {
setupData("loadMeasuresFromDate");
DefaultTimeMachine timeMachine = initTimeMachine();
TimeMachineQuery query = new TimeMachineQuery(newProject()).setFrom(date("2008-02-01")).setMetrics(Arrays.asList(CoreMetrics.NCLOC));
List<Measure> measures = timeMachine.getMeasures(query);
assertThat(measures.size(), is(3));
long previous = 0;
for (Measure measure : measures) {
assertThat(measure.getMetric(), is(CoreMetrics.NCLOC));
assertThat(measure.getDate().getTime(), greaterThan(previous));
previous = measure.getDate().getTime();
}
assertThat(measures.get(0).getValue(), is(200d));
assertThat(measures.get(1).getValue(), is(230d));
assertThat(measures.get(2).getValue(), is(180d));
}
@Test(timeout = 3000)
public void loadMeasuresFromDateInterval() throws ParseException {
setupData("loadMeasuresFromDate");
DefaultTimeMachine timeMachine = initTimeMachine();
TimeMachineQuery query = new TimeMachineQuery(newProject()).setFrom(date("2008-01-01")).setTo(date("2008-12-25")).setMetrics(Arrays.asList(CoreMetrics.NCLOC));
List<Measure> measures = timeMachine.getMeasures(query);
assertThat(measures.size(), is(1));
assertThat(measures.get(0).getValue(), is(200d));
}
private Date date(String date) throws ParseException {
return new SimpleDateFormat("yyyy-MM-dd").parse(date);
}
}
///*
// * Sonar, open source software quality management tool.
// * Copyright (C) 2009 SonarSource SA
// * mailto:contact AT sonarsource DOT com
// *
// * Sonar 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.
// *
// * Sonar 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 Sonar; if not, write to the Free Software
// * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
// */
//package org.sonar.batch;
//
//import org.junit.Test;
//import org.sonar.api.batch.TimeMachineQuery;
//import org.sonar.jpa.dao.MeasuresDao;
//import org.sonar.jpa.test.AbstractDbUnitTestCase;
//import org.sonar.api.measures.CoreMetrics;
//import org.sonar.api.measures.Measure;
//import org.sonar.api.resources.Project;
//import org.sonar.api.resources.Resource;
//import org.sonar.batch.indexer.DefaultSonarIndex;
//
//import java.text.ParseException;
//import java.text.SimpleDateFormat;
//import java.util.Arrays;
//import java.util.Date;
//import java.util.List;
//
//import static org.hamcrest.CoreMatchers.is;
//import static org.hamcrest.number.OrderingComparisons.greaterThan;
//import static org.junit.Assert.assertThat;
//import static org.mockito.Matchers.anyObject;
//import static org.mockito.Mockito.mock;
//import static org.mockito.Mockito.when;
//
//public class DefaultTimeMachineTest extends AbstractDbUnitTestCase {
//
// @Test(timeout = 3000)
// public void loadMeasureFieldsFromDate() throws ParseException {
// setupData("loadMeasuresFromDate");
// DefaultTimeMachine timeMachine = initTimeMachine();
//
// TimeMachineQuery query = new TimeMachineQuery(newProject()).setFrom(date("2008-02-01")).setMetrics(Arrays.asList(CoreMetrics.NCLOC));
// List<Object[]> measures = timeMachine.getMeasuresFields(query);
//
// assertThat(measures.size(), is(3));
// for (Object[] measure : measures) {
// assertThat(measure.length, is(3)); // 3 fields
// assertThat(measure[1], is((Object) CoreMetrics.NCLOC));
// }
// assertThat(measures.get(0)[2], is((Object) 200d));
// assertThat(measures.get(1)[2], is((Object) 230d));
// assertThat(measures.get(2)[2], is((Object) 180d));
// }
//
// private DefaultTimeMachine initTimeMachine() {
// DefaultSonarIndex index = mock(DefaultSonarIndex.class);
// DefaultTimeMachine timeMachine = new DefaultTimeMachine(getSession(), index, new MeasuresDao(getSession()));
// return timeMachine;
// }
//
// private Project newProject() {
// Project project = new Project("group:artifact");
// project.setId(1);
// return project;
// }
//
// @Test(timeout = 3000)
// public void loadMeasuresFromDate() throws ParseException {
// setupData("loadMeasuresFromDate");
// DefaultTimeMachine timeMachine = initTimeMachine();
//
//
// TimeMachineQuery query = new TimeMachineQuery(newProject()).setFrom(date("2008-02-01")).setMetrics(Arrays.asList(CoreMetrics.NCLOC));
// List<Measure> measures = timeMachine.getMeasures(query);
//
// assertThat(measures.size(), is(3));
// long previous = 0;
// for (Measure measure : measures) {
// assertThat(measure.getMetric(), is(CoreMetrics.NCLOC));
// assertThat(measure.getDate().getTime(), greaterThan(previous));
// previous = measure.getDate().getTime();
// }
// assertThat(measures.get(0).getValue(), is(200d));
// assertThat(measures.get(1).getValue(), is(230d));
// assertThat(measures.get(2).getValue(), is(180d));
// }
//
// @Test(timeout = 3000)
// public void loadMeasuresFromDateInterval() throws ParseException {
// setupData("loadMeasuresFromDate");
// DefaultTimeMachine timeMachine = initTimeMachine();
//
//
// TimeMachineQuery query = new TimeMachineQuery(newProject()).setFrom(date("2008-01-01")).setTo(date("2008-12-25")).setMetrics(Arrays.asList(CoreMetrics.NCLOC));
// List<Measure> measures = timeMachine.getMeasures(query);
// assertThat(measures.size(), is(1));
// assertThat(measures.get(0).getValue(), is(200d));
// }
//
// private Date date(String date) throws ParseException {
// return new SimpleDateFormat("yyyy-MM-dd").parse(date);
// }
//}

+ 110
- 0
sonar-batch/src/test/java/org/sonar/batch/index/BucketTest.java View File

@@ -0,0 +1,110 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import org.junit.Test;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.MeasuresFilters;
import org.sonar.api.measures.Metric;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.JavaPackage;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.Violation;
import org.sonar.api.utils.SonarException;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.core.IsNot.not;
import static org.junit.Assert.*;
import static org.junit.internal.matchers.IsCollectionContaining.hasItem;

public class BucketTest {

private JavaPackage javaPackage = new JavaPackage("org.foo");
private JavaFile javaFile = new JavaFile("org.foo.Bar");
private Metric ncloc = new Metric("ncloc");

@Test
public void shouldManageRelationships() {
Bucket packageBucket = new Bucket(javaPackage);
Bucket fileBucket = new Bucket(javaFile);
fileBucket.setParent(packageBucket);

assertThat(fileBucket.getParent(), is(packageBucket));
assertThat(packageBucket.getChildren().size(), is(1));
assertThat(packageBucket.getChildren(), hasItem(fileBucket));
}

@Test
public void shouldCacheViolations() {
Bucket fileBucket = new Bucket(javaFile);
Violation violation = Violation.create(Rule.create("checkstyle", "rule1", "Rule one"), javaFile);
fileBucket.addViolation(violation);
assertThat(fileBucket.getViolations().size(), is(1));
assertThat(fileBucket.getViolations(), hasItem(violation));
}

@Test
public void shouldAddNewMeasure() {
Bucket fileBucket = new Bucket(javaFile);
Measure measure = new Measure(ncloc).setValue(1200.0);
fileBucket.addMeasure(measure);

assertThat(fileBucket.getMeasures(MeasuresFilters.all()).size(), is(1));
assertThat(fileBucket.getMeasures(MeasuresFilters.metric(ncloc)), is(measure));
}

@Test
public void shouldUpdateMeasure() {
Bucket fileBucket = new Bucket(javaFile);
Measure measure = new Measure(ncloc).setValue(1200.0);
fileBucket.addMeasure(measure);

assertThat(fileBucket.getMeasures(MeasuresFilters.all()).size(), is(1));
assertThat(fileBucket.getMeasures(MeasuresFilters.metric(ncloc)).getValue(), is(1200.0));

measure.setValue(500.0);
fileBucket.addMeasure(measure);

assertThat(fileBucket.getMeasures(MeasuresFilters.all()).size(), is(1));
assertThat(fileBucket.getMeasures(MeasuresFilters.metric(ncloc)).getValue(), is(500.0));
}

@Test(expected = SonarException.class)
public void shouldFailIfAddingSameMeasures() {
Bucket fileBucket = new Bucket(javaFile);
Measure measure = new Measure(ncloc).setValue(1200.0);
fileBucket.addMeasure(measure);

measure = new Measure(ncloc).setValue(500.0);
fileBucket.addMeasure(measure);
}

@Test
public void shouldBeEquals() {
assertEquals(new Bucket(javaPackage), new Bucket(javaPackage));
assertEquals(new Bucket(javaPackage).hashCode(), new Bucket(javaPackage).hashCode());
}

@Test
public void shouldNotBeEquals() {
assertFalse(new Bucket(javaPackage).equals(new Bucket(javaFile)));
assertThat(new Bucket(javaPackage).hashCode(), not(is(new Bucket(javaFile).hashCode())));
}
}

sonar-batch/src/main/java/org/sonar/batch/CoreJob.java → sonar-batch/src/test/java/org/sonar/batch/index/DefaultIndexTest.java View File

@@ -17,13 +17,11 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.batch.index;

import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.Project;
import org.junit.Ignore;

public interface CoreJob {

void execute(Project project, SensorContext context);
@Ignore("to do")
public class DefaultIndexTest {

}

+ 133
- 0
sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java View File

@@ -0,0 +1,133 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.sonar.api.database.model.MeasureModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.PersistenceMode;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.JavaPackage;
import org.sonar.api.resources.Project;
import org.sonar.jpa.test.AbstractDbUnitTestCase;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class MeasurePersisterTest extends AbstractDbUnitTestCase {

private ResourcePersister resourcePersister;
private MeasurePersister measurePersister;
private Project project = new Project("foo");
private JavaPackage aPackage = new JavaPackage("org.foo");
private Snapshot projectSnapshot, packageSnapshot;
private Metric ncloc, coverage;

@Before
public void mockResourcePersister() {
setupData("shared");
resourcePersister = mock(ResourcePersister.class);
projectSnapshot = getSession().getSingleResult(Snapshot.class, "id", 3001);
packageSnapshot = getSession().getSingleResult(Snapshot.class, "id", 3002);
ncloc = getSession().getSingleResult(Metric.class, "key", "ncloc");
coverage = getSession().getSingleResult(Metric.class, "key", "coverage");
when(resourcePersister.saveResource((Project) anyObject(), eq(project))).thenReturn(projectSnapshot);
when(resourcePersister.saveResource((Project) anyObject(), eq(aPackage))).thenReturn(packageSnapshot);
measurePersister = new MeasurePersister(getSession(), resourcePersister);
}

@Test
public void shouldInsertMeasure() {
Measure measure = new Measure(ncloc).setValue(1234.0);

measurePersister.saveMeasure(project, measure);

checkTables("shouldInsertMeasure", "project_measures");
}

@Test
public void shouldUpdateMeasure() {
Measure measure = new Measure(coverage).setValue(12.5);
measure.setId(1L);

measurePersister.saveMeasure(project, measure);

checkTables("shouldUpdateMeasure", "project_measures");
}

@Test
@Ignore("to do")
public void shouldInsertDataMeasure() {

}

@Test
public void shouldDelaySaving() {
measurePersister.setDelayedMode(true);

measurePersister.saveMeasure(project, new Measure(ncloc).setValue(1234.0));
measurePersister.saveMeasure(project, aPackage, new Measure(ncloc).setValue(50.0));

assertThat(getSession().getResults(MeasureModel.class, "metricId", 1).size(), is(0));

measurePersister.dump();
checkTables("shouldDelaySaving", "project_measures");
}

@Test
public void shouldNotDelaySavingWithDatabaseOnlyMeasure() {
measurePersister.setDelayedMode(true);

measurePersister.saveMeasure(project, new Measure(ncloc).setValue(1234.0).setPersistenceMode(PersistenceMode.DATABASE)); // database only
measurePersister.saveMeasure(project, aPackage, new Measure(ncloc).setValue(50.0)); // database + memory

// no dump => the db-only measure is saved

checkTables("shouldNotDelaySavingWithDatabaseOnlyMeasure", "project_measures");
}

@Test
public void shouldNotSaveBestValues() {
JavaFile file = new JavaFile("org.foo.MyClass");

Measure measure = new Measure(coverage).setValue(0.0);
assertThat(MeasurePersister.shouldPersistMeasure(file, measure), is(true));

measure = new Measure(coverage).setValue(75.8);
assertThat(MeasurePersister.shouldPersistMeasure(file, measure), is(true));

measure = new Measure(coverage).setValue(100.0);
assertThat(MeasurePersister.shouldPersistMeasure(file, measure), is(false));
}

@Test
public void shouldNotSaveMemoryOnlyMeasures() {
Measure measure = new Measure("ncloc").setPersistenceMode(PersistenceMode.MEMORY);
assertThat(MeasurePersister.shouldPersistMeasure(aPackage, measure), is(false));
}
}

+ 140
- 0
sonar-batch/src/test/java/org/sonar/batch/index/ResourcePersisterTest.java View File

@@ -0,0 +1,140 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.index;

import org.junit.Before;
import org.junit.Test;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.JavaPackage;
import org.sonar.api.resources.Library;
import org.sonar.api.resources.Project;
import org.sonar.jpa.test.AbstractDbUnitTestCase;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.notNullValue;

public class ResourcePersisterTest extends AbstractDbUnitTestCase {

private Project singleProject, multiModuleProject, moduleA, moduleB, moduleB1;

@Before
public void before() throws ParseException {
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
singleProject = new Project("foo");
singleProject.setName("Foo").setDescription("some description").setLanguageKey("java").setAnalysisDate(format.parse("25/12/2010"));

multiModuleProject = new Project("root");
multiModuleProject.setName("Root").setLanguageKey("java").setAnalysisDate(format.parse("25/12/2010"));

moduleA = new Project("a");
moduleA.setName("A").setLanguageKey("java").setAnalysisDate(format.parse("25/12/2010"));
moduleA.setParent(multiModuleProject);

moduleB = new Project("b");
moduleB.setName("B").setLanguageKey("java").setAnalysisDate(format.parse("25/12/2010"));
moduleB.setParent(multiModuleProject);

moduleB1 = new Project("b1");
moduleB1.setName("B1").setLanguageKey("java").setAnalysisDate(format.parse("25/12/2010"));
moduleB1.setParent(moduleB);
}


@Test
public void shouldSaveNewProject() {
setupData("shared");

ResourcePersister persister = new ResourcePersister(getSession());
persister.saveProject(singleProject);

checkTables("shouldSaveNewProject", "projects", "snapshots");
}

@Test
public void shouldSaveNewMultiModulesProject() throws ParseException {
setupData("shared");

ResourcePersister persister = new ResourcePersister(getSession());
persister.saveProject(multiModuleProject);
persister.saveProject(moduleA);
persister.saveProject(moduleB);
persister.saveProject(moduleB1);

checkTables("shouldSaveNewMultiModulesProject", "projects", "snapshots");
}

@Test
public void shouldSaveNewDirectory() {
setupData("shared");

ResourcePersister persister = new ResourcePersister(getSession());
persister.saveProject(singleProject);
persister.saveResource(singleProject, new JavaPackage("org.foo"));

// check that the directory is attached to the project
checkTables("shouldSaveNewDirectory", "projects", "snapshots");
}

@Test
public void shouldSaveNewLibrary() {
setupData("shared");

ResourcePersister persister = new ResourcePersister(getSession());
persister.saveProject(singleProject);
persister.saveResource(singleProject, new Library("junit:junit", "4.8.2"));
persister.saveResource(singleProject, new Library("junit:junit", "4.8.2"));// do nothing, already saved
persister.saveResource(singleProject, new Library("junit:junit", "3.2"));

checkTables("shouldSaveNewLibrary", "projects", "snapshots");
}

@Test
public void shouldClearResourcesExceptProjects() {
setupData("shared");

ResourcePersister persister = new ResourcePersister(getSession());
persister.saveProject(multiModuleProject);
persister.saveProject(moduleA);
persister.saveResource(moduleA, new JavaPackage("org.foo"));
persister.saveResource(moduleA, new JavaFile("org.foo.MyClass"));
persister.clear();

assertThat(persister.getSnapshotsByResource().size(), is(2));
assertThat(persister.getSnapshotsByResource().get(multiModuleProject), notNullValue());
assertThat(persister.getSnapshotsByResource().get(moduleA), notNullValue());
}

@Test
public void shouldUpdateExistingResource() {
setupData("shouldUpdateExistingResource");

ResourcePersister persister = new ResourcePersister(getSession());
singleProject.setName("new name");
singleProject.setDescription("new description");
persister.saveProject(singleProject);

checkTables("shouldUpdateExistingResource", "projects", "snapshots");
}
}

+ 0
- 61
sonar-batch/src/test/java/org/sonar/batch/indexer/DefaultPersisterTest.java View File

@@ -1,61 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.indexer;

import org.junit.Test;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.JavaPackage;
import org.sonar.api.resources.Project;

public class DefaultPersisterTest extends AbstractDbUnitTestCase {

@Test
public void createResource() {
setupData("createResource");

Bucket bucket = createBucket(new JavaPackage("org.foo"));

new DefaultPersister(getSession()).persist(bucket);

checkTables("createResource", "projects", "snapshots");
}

private Bucket createBucket(JavaPackage resource) {
Bucket projectBucket = new Bucket(new Project("my:key").setId(5));
projectBucket.setSnapshot(getSession().getSingleResult(Snapshot.class, "id", 30));

Bucket bucket = new Bucket(resource);
bucket.setProject(projectBucket);
bucket.setParent(projectBucket);
return bucket;
}

@Test
public void updateExistingResource() {
setupData("updateExistingResource");

Bucket bucket = createBucket(new JavaPackage("org.foo"));

new DefaultPersister(getSession()).persist(bucket);

checkTables("updateExistingResource", "projects", "snapshots");
}
}

+ 0
- 72
sonar-batch/src/test/java/org/sonar/batch/indexer/DefaultSonarIndexTest.java View File

@@ -1,72 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.indexer;

import org.junit.Ignore;
import org.junit.Test;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.PersistenceMode;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.DefaultResourceCreationLock;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
import org.sonar.api.design.Dependency;
import org.sonar.api.resources.JavaFile;
import org.sonar.api.resources.Resource;

import static junit.framework.Assert.assertTrue;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

public class DefaultSonarIndexTest extends AbstractDbUnitTestCase {

@Test
public void indexDependencies() {
DefaultSonarIndex index = new DefaultSonarIndex(getSession(), null, new DefaultResourceCreationLock());

Resource from = new JavaFile("org.foo.Foo");
Resource to = new JavaFile("org.bar.Bar");
Dependency dependency = new Dependency(from, to);

index.registerDependency(dependency);

assertThat(index.getDependencies().size(), is(1));
assertTrue(index.getDependencies().contains(dependency));
assertThat(index.getEdge(from, to), is(dependency));

assertThat(index.getIncomingEdges(to).size(), is(1));
assertTrue(index.getIncomingEdges(to).contains(dependency));
assertThat(index.getIncomingEdges(from).isEmpty(), is(true));

assertThat(index.getOutgoingEdges(from).size(), is(1));
assertTrue(index.getOutgoingEdges(from).contains(dependency));
assertThat(index.getOutgoingEdges(to).isEmpty(), is(true));
}

@Test(expected = SonarException.class)
@Ignore("Temporarily log warnings instead of throwing an exception")
public void failIfLockedAndAddingMeasureOnUnknownResource() {
DefaultResourceCreationLock lock = new DefaultResourceCreationLock();
lock.lock();

DefaultSonarIndex index = new DefaultSonarIndex(getSession(), null, lock);
index.saveMeasure(new JavaFile("org.foo.Bar"), new Measure(CoreMetrics.LINES, 200.0));
}
}

+ 0
- 94
sonar-batch/src/test/java/org/sonar/batch/indexer/LibraryPersisterTest.java View File

@@ -1,94 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.indexer;

import org.junit.Before;
import org.junit.Test;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Library;
import org.sonar.api.resources.Project;

import java.text.ParseException;
import java.text.SimpleDateFormat;

public class LibraryPersisterTest extends AbstractDbUnitTestCase {

private Bucket<Project> projectBucket;
private LibraryPersister persister;

@Before
public void before() throws ParseException {
persister = new LibraryPersister(getSession(), new SimpleDateFormat("yyyy-MM-dd HH:mm").parse( "2010-05-18 17:00"));
}

@Test
public void createLibrary() throws Exception {
setup("createLibrary");

Library library = new Library("commons-lang:commons-lang", "1.1")
.setName("Commons Lang");

Bucket<Library> bucket = new Bucket<Library>(library).setProject(projectBucket);
persister.persist(bucket);

check("createLibrary", "projects", "snapshots");
}

@Test
public void reuseExistingLibrary() throws Exception {
setup("reuseExistingLibrary");

Library library = new Library("commons-lang:commons-lang", "1.1")
.setName("Commons Lang");

Bucket<Library> bucket = new Bucket<Library>(library).setProject(projectBucket);
persister.persist(bucket);

check("reuseExistingLibrary", "projects", "snapshots");
}

@Test
public void addNewLibraryVersion() throws Exception {
setup("addNewLibraryVersion");

Library library = new Library("commons-lang:commons-lang", "1.2")
.setName("Commons Lang");

Bucket<Library> bucket = new Bucket<Library>(library).setProject(projectBucket);
persister.persist(bucket);

check("addNewLibraryVersion", "projects", "snapshots");
}

private void setup(String unitTest) throws Exception {
setupData(unitTest);

Project project = new Project("my:project");
project.setId(1);
projectBucket = new Bucket<Project>(project);
projectBucket.setSnapshot(getSession().getSingleResult(Snapshot.class, "id", 1));
}

private void check(String unitTest, String... tables) {
getSession().commit();
checkTables(unitTest, tables);
}
}

+ 0
- 67
sonar-batch/src/test/java/org/sonar/batch/indexer/ResourcePersistersTest.java View File

@@ -1,67 +0,0 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.indexer;

import org.junit.Test;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
import org.sonar.api.resources.*;

import static junit.framework.Assert.assertTrue;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

public class ResourcePersistersTest extends AbstractDbUnitTestCase {

@Test
public void getDefaultPersisterForFilesAndPackages() {
ResourcePersisters persisters = new ResourcePersisters(getSession());


JavaFile file = new JavaFile("org.foo.Bar");
assertThat(persisters.get(file), is(DefaultPersister.class));
assertThat(persisters.get(new JavaPackage("org.foo")), is(DefaultPersister.class));
assertThat(persisters.get(new File("org/foo/Bar.sql")), is(DefaultPersister.class));

// always the same instance
assertTrue(persisters.get(file)==persisters.get(file));
}

@Test
public void getForProjects() {
ResourcePersisters persisters = new ResourcePersisters(getSession());

Project project = new Project("my:project");
assertThat(persisters.get(project), is(ProjectPersister.class));

// always the same instance
assertTrue(persisters.get(project)==persisters.get(project));
}

@Test
public void getForLibraries() {
ResourcePersisters persisters = new ResourcePersisters(getSession());

Library lib = new Library("commons-lang:commons-lang", "1.0");
assertThat(persisters.get(lib), is(LibraryPersister.class));

// always the same instance
assertTrue(persisters.get(lib)==persisters.get(lib));
}
}

sonar-batch/src/test/java/org/sonar/batch/MavenPhaseExecutorTest.java → sonar-batch/src/test/java/org/sonar/batch/phases/MavenPhaseExecutorTest.java View File

@@ -17,12 +17,12 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.batch.phases;

import org.apache.commons.configuration.PropertiesConfiguration;
import org.junit.Test;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.Project;
import org.sonar.batch.MavenPluginExecutor;

import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.*;
@@ -36,7 +36,7 @@ public class MavenPhaseExecutorTest {


Project project = new Project("key");
phaseExecutor.execute(project, mock(SensorContext.class));
phaseExecutor.execute(project);

verify(mavenPluginExecutor, never()).execute(eq(project), anyString());
}
@@ -51,7 +51,7 @@ public class MavenPhaseExecutorTest {
conf.setProperty(MavenPhaseExecutor.PROP_PHASE, "myphase");
project.setConfiguration(conf);

phaseExecutor.execute(project, mock(SensorContext.class));
phaseExecutor.execute(project);

verify(mavenPluginExecutor).execute(project, "myphase");
}

sonar-batch/src/test/java/org/sonar/batch/MavenPluginsConfiguratorTest.java → sonar-batch/src/test/java/org/sonar/batch/phases/MavenPluginsConfiguratorTest.java View File

@@ -17,18 +17,16 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.batch.phases;

import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Test;
import org.sonar.api.batch.BatchExtensionDictionnary;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.batch.maven.MavenPlugin;
import org.sonar.api.batch.maven.MavenPluginHandler;
import org.sonar.api.resources.Project;
import org.sonar.api.test.MavenTestUtils;
import org.sonar.api.utils.ServerHttpClient;

import java.util.Arrays;

@@ -53,7 +51,7 @@ public class MavenPluginsConfiguratorTest {

Project project = MavenTestUtils.loadProjectFromPom(getClass(), "pom.xml");

newConfigurator(handler1, handler2).execute(project, mock(SensorContext.class));
newConfigurator(handler1, handler2).execute(project);

verify(handler1).configure(eq(project), argThat(new IsMavenPlugin("myartifact1")));
verify(handler2).configure(eq(project), argThat(new IsMavenPlugin("myartifact2")));

+ 33
- 0
sonar-batch/src/test/java/org/sonar/batch/phases/PhasesTest.java View File

@@ -0,0 +1,33 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch.phases;

import org.junit.Test;

import static org.hamcrest.number.OrderingComparisons.greaterThan;
import static org.junit.Assert.assertThat;

public class PhasesTest {

@Test
public void shouldDefinePhaseClasses() {
assertThat(Phases.getPhaseClasses().size(), greaterThan(4));
}
}

sonar-batch/src/test/java/org/sonar/batch/PostJobsExecutorTest.java → sonar-batch/src/test/java/org/sonar/batch/phases/PostJobsExecutorTest.java View File

@@ -17,32 +17,22 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.batch.phases;

import org.junit.Test;
import org.sonar.api.batch.PostJob;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.resources.Project;
import org.sonar.batch.MavenPluginExecutor;

import java.util.Arrays;
import java.util.List;

import static org.mockito.Matchers.anyObject;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

public class PostJobsExecutorTest {

@Test
public void doNotExecuteOnModules() {
PostJob job1 = mock(PostJob.class);
Project module = new Project("module").setParent(new Project("project"));

PostJobsExecutor executor = new PostJobsExecutor(Arrays.<PostJob>asList(job1), mock(MavenPluginExecutor.class));
executor.execute(module, mock(SensorContext.class));

verify(job1, never()).executeOn((Project) anyObject(), (SensorContext) anyObject());
}

@Test
public void executeAllPostJobs() {
PostJob job1 = mock(PostJob.class);
@@ -58,9 +48,4 @@ public class PostJobsExecutorTest {
verify(job2).executeOn(project, context);

}

static class FakePostJob implements PostJob {
public void executeOn(Project project, SensorContext context) {
}
}
}

sonar-batch/src/test/java/org/sonar/batch/FinalizeSnapshotsJobTest.java → sonar-batch/src/test/java/org/sonar/batch/phases/UpdateStatusJobTest.java View File

@@ -17,19 +17,18 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.batch.phases;

import org.junit.Test;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Project;
import org.sonar.batch.ServerMetadata;
import org.sonar.jpa.test.AbstractDbUnitTestCase;

import javax.persistence.Query;

import static org.mockito.Mockito.mock;

public class FinalizeSnapshotsJobTest extends AbstractDbUnitTestCase {

public class UpdateStatusJobTest extends AbstractDbUnitTestCase {

@Test
public void shouldUnflagPenultimateLastSnapshot() throws Exception {
@@ -49,8 +48,8 @@ public class FinalizeSnapshotsJobTest extends AbstractDbUnitTestCase {
private void assertAnalysis(int snapshotId, String fixture) {
setupData("sharedFixture", fixture);

FinalizeSnapshotsJob sensor = new FinalizeSnapshotsJob(mock(ServerMetadata.class), getSession(), loadSnapshot(snapshotId));
sensor.execute(new Project("key"), null);
UpdateStatusJob sensor = new UpdateStatusJob(mock(ServerMetadata.class), getSession(), loadSnapshot(snapshotId));
sensor.execute();

getSession().stop();
checkTables(fixture, "snapshots");

+ 0
- 22
sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/doNotFailIfNoPenultimateLast-result.xml View File

@@ -1,22 +0,0 @@
<dataset>
<!-- currently processing snapshots -->
<snapshots depth="[null]" id="5" scope="PRJ" qualifier="TRK" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="6" scope="PRJ" qualifier="TRK" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="2"
parent_snapshot_id="5" root_project_id="[null]" root_snapshot_id="5" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="7" scope="DIR" qualifier="PAC" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="3"
parent_snapshot_id="6" root_project_id="[null]" root_snapshot_id="5" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="8" scope="FIL" qualifier="CLA" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="4"
parent_snapshot_id="7" root_project_id="[null]" root_snapshot_id="5" status="P" islast="true"
path="[null]"/>
</dataset>

+ 0
- 23
sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/doNotFailIfNoPenultimateLast.xml View File

@@ -1,23 +0,0 @@
<dataset>

<!-- currently processing snapshots -->
<snapshots depth="[null]" id="5" scope="PRJ" qualifier="TRK" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="U" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="6" scope="PRJ" qualifier="TRK" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="2"
parent_snapshot_id="5" root_project_id="[null]" root_snapshot_id="5" status="U" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="7" scope="DIR" qualifier="PAC" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="3"
parent_snapshot_id="6" root_project_id="[null]" root_snapshot_id="5" status="U" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="8" scope="FIL" qualifier="CLA" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="4"
parent_snapshot_id="7" root_project_id="[null]" root_snapshot_id="5" status="U" islast="false"
path="[null]"/>
</dataset>

+ 0
- 173
sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/lastSnapshotIsNotUpdatedWhenAnalyzingPastSnapshot-result.xml View File

@@ -1,173 +0,0 @@
<dataset>

<!-- last snapshot : is always last, and not purged -->
<snapshots depth="[null]" id="1" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="2" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="2"
parent_snapshot_id="1" root_project_id="[null]" root_snapshot_id="1" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="3" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="3"
parent_snapshot_id="2" root_project_id="[null]" root_snapshot_id="1" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="4" scope="FIL" qualifier="CLA" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="4"
parent_snapshot_id="3" root_project_id="[null]" root_snapshot_id="1" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="5" scope="FIL" qualifier="CLA" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="5"
parent_snapshot_id="3" root_project_id="[null]" root_snapshot_id="1" status="P" islast="true"
path="[null]"/>


<!-- the snapshot to process : not set as last-->
<snapshots depth="[null]" id="6" scope="PRJ" qualifier="TRK" created_at="2005-10-01 00:00:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="7" scope="PRJ" qualifier="TRK" created_at="2005-10-01 00:00:00.00" version="[null]"
project_id="2"
parent_snapshot_id="6" root_project_id="[null]" root_snapshot_id="6" status="P" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="8" scope="DIR" qualifier="PAC" created_at="2005-10-01 00:00:00.00" version="[null]"
project_id="3"
parent_snapshot_id="7" root_project_id="[null]" root_snapshot_id="6" status="P" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="9" scope="FIL" qualifier="CLA" created_at="2005-10-01 00:00:00.00" version="[null]"
project_id="4"
parent_snapshot_id="8" root_project_id="[null]" root_snapshot_id="6" status="P" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="10" scope="FIL" qualifier="CLA" created_at="2005-10-01 00:00:00.00" version="[null]"
project_id="5"
parent_snapshot_id="9" root_project_id="[null]" root_snapshot_id="6" status="P" islast="false"
path="[null]"/>


<SNAPSHOT_SOURCES ID="1" SNAPSHOT_ID="4" DATA="source code of Class1"/>
<SNAPSHOT_SOURCES ID="2" SNAPSHOT_ID="5" DATA="source code of Class2"/>

<RULE_FAILURES ID="1" SNAPSHOT_ID="4" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg1" COST="[null]"/>
<RULE_FAILURES ID="2" SNAPSHOT_ID="4" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg2" COST="[null]"/>
<RULE_FAILURES ID="3" SNAPSHOT_ID="4" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg3" COST="[null]"/>
<RULE_FAILURES ID="4" SNAPSHOT_ID="4" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg4" COST="[null]"/>

<RULE_FAILURES ID="5" SNAPSHOT_ID="5" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg5" COST="[null]"/>
<RULE_FAILURES ID="6" SNAPSHOT_ID="5" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg6" COST="[null]"/>

<!-- measures at project level -->
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="1" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="1" RULES_CATEGORY_ID="1"
RULE_ID="1"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="2" VALUE="20.0" METRIC_ID="2" SNAPSHOT_ID="1" RULES_CATEGORY_ID="1"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="3" VALUE="30.0" METRIC_ID="3" SNAPSHOT_ID="1" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>

<!-- measures at module level -->
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="4" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="2" RULES_CATEGORY_ID="1"
RULE_ID="1"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="5" VALUE="20.0" METRIC_ID="2" SNAPSHOT_ID="2" RULES_CATEGORY_ID="1"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="6" VALUE="30.0" METRIC_ID="3" SNAPSHOT_ID="2" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>

<!-- measures at package level -->
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="7" VALUE="40.0" METRIC_ID="1" SNAPSHOT_ID="3" RULES_CATEGORY_ID="[null]"
RULE_ID="1"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="8" VALUE="50.0" METRIC_ID="2" SNAPSHOT_ID="3" RULES_CATEGORY_ID="1"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="9" VALUE="60.0" METRIC_ID="3" SNAPSHOT_ID="3" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="10" VALUE="60.0" METRIC_ID="3" SNAPSHOT_ID="3" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>

<!-- measures at class level -->
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="11" VALUE="40.0" METRIC_ID="1" SNAPSHOT_ID="4" RULES_CATEGORY_ID="1"
RULE_ID="1"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="12" VALUE="50.0" METRIC_ID="2" SNAPSHOT_ID="4" RULES_CATEGORY_ID="1"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="13" VALUE="60.0" METRIC_ID="3" SNAPSHOT_ID="4" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>

<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="14" VALUE="40.0" METRIC_ID="1" SNAPSHOT_ID="5" RULES_CATEGORY_ID="1"
RULE_ID="1"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="15" VALUE="50.0" METRIC_ID="2" SNAPSHOT_ID="5" RULES_CATEGORY_ID="1"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="16" VALUE="60.0" METRIC_ID="3" SNAPSHOT_ID="5" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>

</dataset>

+ 0
- 174
sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/lastSnapshotIsNotUpdatedWhenAnalyzingPastSnapshot.xml View File

@@ -1,174 +0,0 @@
<dataset>

<!-- last snapshot -->
<snapshots depth="[null]" id="1" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="2" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="2"
parent_snapshot_id="1" root_project_id="[null]" root_snapshot_id="1" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="3" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="3"
parent_snapshot_id="2" root_project_id="[null]" root_snapshot_id="1" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="4" scope="FIL" qualifier="CLA" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="4"
parent_snapshot_id="3" root_project_id="[null]" root_snapshot_id="1" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="5" scope="FIL" qualifier="CLA" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="5"
parent_snapshot_id="3" root_project_id="[null]" root_snapshot_id="1" status="P" islast="true"
path="[null]"/>


<!-- the snapshot to process -->
<snapshots depth="[null]" id="6" scope="PRJ" qualifier="TRK" created_at="2005-10-01 00:00:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="[null]"
islast="false"
path="[null]"/>

<snapshots depth="[null]" id="7" scope="PRJ" qualifier="TRK" created_at="2005-10-01 00:00:00.00" version="[null]"
project_id="2"
parent_snapshot_id="6" root_project_id="[null]" root_snapshot_id="6" status="[null]" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="8" scope="DIR" qualifier="PAC" created_at="2005-10-01 00:00:00.00" version="[null]"
project_id="3"
parent_snapshot_id="7" root_project_id="[null]" root_snapshot_id="6" status="[null]" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="9" scope="FIL" qualifier="CLA" created_at="2005-10-01 00:00:00.00" version="[null]"
project_id="4"
parent_snapshot_id="8" root_project_id="[null]" root_snapshot_id="6" status="[null]" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="10" scope="FIL" qualifier="CLA" created_at="2005-10-01 00:00:00.00" version="[null]"
project_id="5"
parent_snapshot_id="9" root_project_id="[null]" root_snapshot_id="6" status="[null]" islast="false"
path="[null]"/>


<SNAPSHOT_SOURCES ID="1" SNAPSHOT_ID="4" DATA="source code of Class1"/>
<SNAPSHOT_SOURCES ID="2" SNAPSHOT_ID="5" DATA="source code of Class2"/>

<RULE_FAILURES ID="1" SNAPSHOT_ID="4" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg1" COST="[null]"/>
<RULE_FAILURES ID="2" SNAPSHOT_ID="4" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg2" COST="[null]"/>
<RULE_FAILURES ID="3" SNAPSHOT_ID="4" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg3" COST="[null]"/>
<RULE_FAILURES ID="4" SNAPSHOT_ID="4" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg4" COST="[null]"/>

<RULE_FAILURES ID="5" SNAPSHOT_ID="5" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg5" COST="[null]"/>
<RULE_FAILURES ID="6" SNAPSHOT_ID="5" RULE_ID="1" FAILURE_LEVEL="2" MESSAGE="msg6" COST="[null]"/>

<!-- measures at project level -->
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="1" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="1" RULES_CATEGORY_ID="1"
RULE_ID="1"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="2" VALUE="20.0" METRIC_ID="2" SNAPSHOT_ID="1" RULES_CATEGORY_ID="1"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="3" VALUE="30.0" METRIC_ID="3" SNAPSHOT_ID="1" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>

<!-- measures at module level -->
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="4" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="2" RULES_CATEGORY_ID="1"
RULE_ID="1"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="5" VALUE="20.0" METRIC_ID="2" SNAPSHOT_ID="2" RULES_CATEGORY_ID="1"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="6" VALUE="30.0" METRIC_ID="3" SNAPSHOT_ID="2" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>

<!-- measures at package level -->
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="7" VALUE="40.0" METRIC_ID="1" SNAPSHOT_ID="3" RULES_CATEGORY_ID="[null]"
RULE_ID="1"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="8" VALUE="50.0" METRIC_ID="2" SNAPSHOT_ID="3" RULES_CATEGORY_ID="1"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="9" VALUE="60.0" METRIC_ID="3" SNAPSHOT_ID="3" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="10" VALUE="60.0" METRIC_ID="3" SNAPSHOT_ID="3" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>

<!-- measures at class level -->
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="11" VALUE="40.0" METRIC_ID="1" SNAPSHOT_ID="4" RULES_CATEGORY_ID="1"
RULE_ID="1"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="12" VALUE="50.0" METRIC_ID="2" SNAPSHOT_ID="4" RULES_CATEGORY_ID="1"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="13" VALUE="60.0" METRIC_ID="3" SNAPSHOT_ID="4" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>

<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="14" VALUE="40.0" METRIC_ID="1" SNAPSHOT_ID="5" RULES_CATEGORY_ID="1"
RULE_ID="1"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="15" VALUE="50.0" METRIC_ID="2" SNAPSHOT_ID="5" RULES_CATEGORY_ID="1"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>
<project_measures characteristic_id="[null]" url="[null]" diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"
rule_priority="[null]"
alert_text="[null]" ID="16" VALUE="60.0" METRIC_ID="3" SNAPSHOT_ID="5" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]"
text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]"/>

</dataset>

+ 0
- 38
sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/sharedFixture.xml View File

@@ -1,38 +0,0 @@
<dataset>
<rules_categories id="1" name="category one" description="[null]"/>
<rules id="1" name="foo" rules_category_id="1" plugin_config_key="checker/foo" plugin_rule_key="checkstyle.rule1"
plugin_name="maven-checkstyle-plugin" description="description" cardinality="SINGLE" parent_id="[null]"/>
<metrics id="1" name="ncloc" val_type="INT" description="[null]" domain="[null]"
short_name="" qualitative="false" user_managed="false" enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
<metrics id="2" name="foo" val_type="INT" description="[null]" domain="[null]"
short_name="" qualitative="false" user_managed="false" enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
<metrics id="3" name="bar" val_type="INT" description="[null]" domain="[null]"
short_name="" qualitative="false" user_managed="false" enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
<metrics id="4" name="baz" val_type="INT" description="[null]" domain="[null]"
short_name="" qualitative="false" user_managed="false" enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>

<projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="mygroup:myartifact" name="[null]"
root_id="[null]"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]"/>

<projects long_name="[null]" id="2" scope="PRJ" qualifier="TRK" kee="mygroup:myartifact2" name="[null]" root_id="1"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]"/>

<projects long_name="[null]" id="3" scope="DIR" qualifier="PAC" kee="mygroup:myartifact:my.package" name="[null]"
root_id="1"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]"/>

<projects long_name="[null]" id="4" scope="FIL" qualifier="CLA" kee="mygroup:myartifact:my.package.Class1"
name="[null]" root_id="1"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]"/>

<projects long_name="[null]" id="5" scope="FIL" qualifier="CLA" kee="mygroup:myartifact:my.package.Class2"
name="[null]" root_id="1"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]"/>
</dataset>

+ 0
- 55
sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/shouldUnflagPenultimateLastSnapshot-result.xml View File

@@ -1,55 +0,0 @@
<dataset>

<!-- previous last snapshots -->
<snapshots depth="[null]" id="1" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="2" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="2"
parent_snapshot_id="1" root_project_id="[null]" root_snapshot_id="1" status="P" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="3" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="3"
parent_snapshot_id="2" root_project_id="[null]" root_snapshot_id="1" status="P" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="4" scope="FIL" qualifier="CLA" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="4"
parent_snapshot_id="3" root_project_id="[null]" root_snapshot_id="1" status="P" islast="false"
path="[null]"/>

<!-- already purged snapshot -->
<snapshots depth="[null]" id="9" scope="PRJ" qualifier="TRK" created_at="2008-10-02 13:58:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="10" scope="PRJ" qualifier="TRK" created_at="2008-10-02 13:58:00.00" version="[null]"
project_id="2"
parent_snapshot_id="9" root_project_id="[null]" root_snapshot_id="9" status="P" islast="false"
path="[null]"/>

<!-- currently processing snapshots -->
<snapshots depth="[null]" id="11" scope="PRJ" qualifier="TRK" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="12" scope="PRJ" qualifier="TRK" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="2"
parent_snapshot_id="11" root_project_id="[null]" root_snapshot_id="11" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="13" scope="DIR" qualifier="PAC" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="3"
parent_snapshot_id="12" root_project_id="[null]" root_snapshot_id="11" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="14" scope="FIL" qualifier="CLA" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="4"
parent_snapshot_id="13" root_project_id="[null]" root_snapshot_id="11" status="P" islast="true"
path="[null]"/>
</dataset>

+ 0
- 57
sonar-batch/src/test/resources/org/sonar/batch/FinalizeSnapshotsJobTest/shouldUnflagPenultimateLastSnapshot.xml View File

@@ -1,57 +0,0 @@
<dataset>

<!-- previous last snapshots -->
<snapshots depth="[null]" id="1" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="2" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="2"
parent_snapshot_id="1" root_project_id="[null]" root_snapshot_id="1" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="3" scope="DIR" qualifier="PAC" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="3"
parent_snapshot_id="2" root_project_id="[null]" root_snapshot_id="1" status="P" islast="true"
path="[null]"/>

<snapshots depth="[null]" id="4" scope="FIL" qualifier="CLA" created_at="2008-12-02 13:58:00.00" version="[null]"
project_id="4"
parent_snapshot_id="3" root_project_id="[null]" root_snapshot_id="1" status="P" islast="true"
path="[null]"/>


<!-- already purged snapshot -->
<snapshots depth="[null]" id="9" scope="PRJ" qualifier="TRK" created_at="2008-10-02 13:58:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="P" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="10" scope="PRJ" qualifier="TRK" created_at="2008-10-02 13:58:00.00" version="[null]"
project_id="2"
parent_snapshot_id="9" root_project_id="[null]" root_snapshot_id="9" status="P" islast="false"
path="[null]"/>


<!-- currently processing snapshots -->
<snapshots depth="[null]" id="11" scope="PRJ" qualifier="TRK" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="1"
parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="U" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="12" scope="PRJ" qualifier="TRK" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="2"
parent_snapshot_id="11" root_project_id="[null]" root_snapshot_id="11" status="U" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="13" scope="DIR" qualifier="PAC" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="3"
parent_snapshot_id="12" root_project_id="[null]" root_snapshot_id="11" status="U" islast="false"
path="[null]"/>

<snapshots depth="[null]" id="14" scope="FIL" qualifier="CLA" created_at="2008-12-04 13:58:00.00" version="[null]"
project_id="4"
parent_snapshot_id="13" root_project_id="[null]" root_snapshot_id="11" status="U" islast="false"
path="[null]"/>
</dataset>

sonar-batch/src/test/resources/org/sonar/batch/MavenPluginsConfiguratorTest/pom.xml → sonar-batch/src/test/resources/org/sonar/batch/MavenProjectBuilderTest/MavenPluginsConfiguratorTest/pom.xml View File


+ 31
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shared.xml View File

@@ -0,0 +1,31 @@
<dataset>

<metrics id="1" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>
<metrics id="2" name="coverage" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
enabled="true" worst_value="0" optimized_best_value="true" best_value="100" direction="1" hidden="false"/>

<projects id="1001" scope="PRJ" qualifier="TRK" kee="foo" root_id="[null]"
name="project name" long_name="project name" description="project description"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects id="1002" scope="DIR" qualifier="PAC" kee="foo:org.foo" root_id="[null]"
name="org.foo" long_name="org.foo" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3001" project_id="1001" parent_snapshot_id="[null]" root_project_id="1001" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-23 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0" />

<snapshots id="3002" project_id="1002" parent_snapshot_id="3001" root_project_id="1001" root_snapshot_id="3001"
scope="DIR" qualifier="PAC" created_at="2010-12-23 00:00:00.00" version="[null]" path="3001."
status="U" islast="false" depth="1" />

<project_measures id="1" VALUE="60" METRIC_ID="2" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"/>



</dataset>

+ 45
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldDelaySaving-result.xml View File

@@ -0,0 +1,45 @@
<dataset>

<metrics id="1" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0"
hidden="false"/>
<metrics id="2" name="coverage" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
enabled="true" worst_value="0" optimized_best_value="true" best_value="100" direction="1" hidden="false"/>

<projects id="1001" scope="PRJ" qualifier="TRK" kee="foo" root_id="[null]"
name="project name" long_name="project name" description="project description"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects id="1002" scope="DIR" qualifier="PAC" kee="foo:org.foo" root_id="[null]"
name="org.foo" long_name="org.foo" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3001" project_id="1001" parent_snapshot_id="[null]" root_project_id="1001" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-23 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0"/>

<snapshots id="3002" project_id="1002" parent_snapshot_id="3001" root_project_id="1001" root_snapshot_id="3001"
scope="DIR" qualifier="PAC" created_at="2010-12-23 00:00:00.00" version="[null]" path="3001."
status="U" islast="false" depth="1"/>

<project_measures id="1" VALUE="60" METRIC_ID="2" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]"
url="[null]"
diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"/>

<project_measures id="2" VALUE="1234.0" METRIC_ID="1" SNAPSHOT_ID="3001" alert_text="[null]"
RULES_CATEGORY_ID="[null]"
RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]"
url="[null]"
diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"/>

<project_measures id="3" VALUE="50.0" METRIC_ID="1" SNAPSHOT_ID="3002" alert_text="[null]" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]"
url="[null]"
diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"/>


</dataset>

+ 35
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldInsertMeasure-result.xml View File

@@ -0,0 +1,35 @@
<dataset>

<metrics id="1" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>

<metrics id="2" name="coverage" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
enabled="true" worst_value="0" optimized_best_value="true" best_value="100" direction="1" hidden="false"/>

<projects id="1001" scope="PRJ" qualifier="TRK" kee="foo" root_id="[null]"
name="project name" long_name="project name" description="project description"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects id="1002" scope="DIR" qualifier="PAC" kee="foo:org.foo" root_id="[null]"
name="org.foo" long_name="org.foo" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3001" project_id="1001" parent_snapshot_id="[null]" root_project_id="1001" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-23 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0" />

<snapshots id="3002" project_id="1002" parent_snapshot_id="3001" root_project_id="1001" root_snapshot_id="3001"
scope="DIR" qualifier="PAC" created_at="2010-12-23 00:00:00.00" version="[null]" path="3001."
status="U" islast="false" depth="1" />

<project_measures id="1" VALUE="60" METRIC_ID="2" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"/>

<project_measures id="2" VALUE="1234.0" METRIC_ID="1" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"/>

</dataset>

+ 42
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldNotDelaySavingWithDatabaseOnlyMeasure-result.xml View File

@@ -0,0 +1,42 @@
<dataset>

<metrics id="1" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>

<metrics id="2" name="coverage" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
enabled="true" worst_value="0" optimized_best_value="true" best_value="100" direction="1" hidden="false"/>

<projects id="1001" scope="PRJ" qualifier="TRK" kee="foo" root_id="[null]"
name="project name" long_name="project name" description="project description"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects id="1002" scope="DIR" qualifier="PAC" kee="foo:org.foo" root_id="[null]"
name="org.foo" long_name="org.foo" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3001" project_id="1001" parent_snapshot_id="[null]" root_project_id="1001" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-23 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0" />

<snapshots id="3002" project_id="1002" parent_snapshot_id="3001" root_project_id="1001" root_snapshot_id="3001"
scope="DIR" qualifier="PAC" created_at="2010-12-23 00:00:00.00" version="[null]" path="3001."
status="U" islast="false" depth="1" />

<project_measures id="1" VALUE="60" METRIC_ID="2" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"/>

<project_measures id="2" VALUE="1234.0" METRIC_ID="1" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"/>

<!-- delayed -->
<!--<project_measures id="3" VALUE="50.0" METRIC_ID="1" SNAPSHOT_ID="3002" alert_text="[null]" RULES_CATEGORY_ID="[null]"-->
<!--RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"-->
<!--alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"-->
<!--diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"/>-->


</dataset>

+ 30
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/MeasurePersisterTest/shouldUpdateMeasure-result.xml View File

@@ -0,0 +1,30 @@
<dataset>

<metrics id="1" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false"/>

<metrics id="2" name="coverage" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
enabled="true" worst_value="0" optimized_best_value="true" best_value="100" direction="1" hidden="false"/>
<projects id="1001" scope="PRJ" qualifier="TRK" kee="foo" root_id="[null]"
name="project name" long_name="project name" description="project description"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects id="1002" scope="DIR" qualifier="PAC" kee="foo:org.foo" root_id="[null]"
name="org.foo" long_name="org.foo" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3001" project_id="1001" parent_snapshot_id="[null]" root_project_id="1001" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-23 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0" />

<snapshots id="3002" project_id="1002" parent_snapshot_id="3001" root_project_id="1001" root_snapshot_id="3001"
scope="DIR" qualifier="PAC" created_at="2010-12-23 00:00:00.00" version="[null]" path="3001."
status="U" islast="false" depth="1" />

<project_measures id="1" VALUE="12.5" METRIC_ID="2" SNAPSHOT_ID="3001" alert_text="[null]" RULES_CATEGORY_ID="[null]"
RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
alert_status="[null]" description="[null]" rule_priority="[null]" characteristic_id="[null]" url="[null]"
diff_value_1="[null]" diff_value_2="[null]" diff_value_3="[null]"/>

</dataset>

+ 12
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shared.xml View File

@@ -0,0 +1,12 @@
<dataset>

<!-- other project -->
<projects id="1000" scope="PRJ" qualifier="TRK" kee="my:key" root_id="[null]"
name="Other project" long_name="Other" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3000" project_id="1000" parent_snapshot_id="[null]" root_project_id="1000" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
status="P" islast="false" depth="0" />

</dataset>

+ 30
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewDirectory-result.xml View File

@@ -0,0 +1,30 @@
<dataset>

<!-- other project -->
<projects id="1000" scope="PRJ" qualifier="TRK" kee="my:key" root_id="[null]"
name="Other project" long_name="Other" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3000" project_id="1000" parent_snapshot_id="[null]" root_project_id="1000" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
status="P" islast="false" depth="0"/>


<!-- new project -->
<projects id="1001" scope="PRJ" qualifier="TRK" kee="foo" root_id="[null]"
name="Foo" long_name="Foo" description="some description"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects id="1002" scope="DIR" qualifier="PAC" kee="foo:org.foo" root_id="1001"
name="org.foo" long_name="org.foo" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3001" project_id="1001" parent_snapshot_id="[null]" root_project_id="1001" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-25 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0"/>

<snapshots id="3002" project_id="1002" parent_snapshot_id="3001" root_project_id="1001" root_snapshot_id="3001"
scope="DIR" qualifier="PAC" created_at="2010-12-25 00:00:00.00" version="[null]" path="3001."
status="U" islast="false" depth="1"/>

</dataset>

+ 34
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewLibrary-result.xml View File

@@ -0,0 +1,34 @@
<dataset>

<!-- other project -->
<projects id="1000" scope="PRJ" qualifier="TRK" kee="my:key" root_id="[null]"
name="Other project" long_name="Other" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3000" project_id="1000" parent_snapshot_id="[null]" root_project_id="1000" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
status="P" islast="false" depth="0" />


<!-- new project -->
<projects id="1001" scope="PRJ" qualifier="TRK" kee="foo" root_id="[null]"
name="Foo" long_name="Foo" description="some description"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects id="1002" scope="PRJ" qualifier="LIB" kee="junit:junit" root_id="[null]"
name="junit:junit" long_name="junit:junit" description="[null]"
enabled="true" language="[null]" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3001" project_id="1001" parent_snapshot_id="[null]" root_project_id="1001" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-25 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0" />

<snapshots id="3002" project_id="1002" parent_snapshot_id="[null]" root_project_id="1002" root_snapshot_id="[null]"
scope="PRJ" qualifier="LIB" created_at="2010-12-25 00:00:00.00" version="4.8.2" path=""
status="P" islast="false" depth="0" />

<snapshots id="3003" project_id="1002" parent_snapshot_id="[null]" root_project_id="1002" root_snapshot_id="[null]"
scope="PRJ" qualifier="LIB" created_at="2010-12-25 00:00:00.00" version="3.2" path=""
status="P" islast="false" depth="0" />

</dataset>

+ 48
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewMultiModulesProject-result.xml View File

@@ -0,0 +1,48 @@
<dataset>

<!-- other project -->
<projects id="1000" scope="PRJ" qualifier="TRK" kee="my:key" root_id="[null]"
name="Other project" long_name="Other" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3000" project_id="1000" parent_snapshot_id="[null]" root_project_id="1000" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
status="P" islast="false" depth="0" />


<!-- new project -->
<projects id="1001" scope="PRJ" qualifier="TRK" kee="root" root_id="[null]"
name="Root" long_name="Root" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects id="1002" scope="PRJ" qualifier="BRC" kee="a" root_id="1001"
name="A" long_name="A" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects id="1003" scope="PRJ" qualifier="BRC" kee="b" root_id="1001"
name="B" long_name="B" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects id="1004" scope="PRJ" qualifier="BRC" kee="b1" root_id="1001"
name="B1" long_name="B1" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>


<snapshots id="3001" project_id="1001" root_project_id="1001" parent_snapshot_id="[null]" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-25 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0" />

<snapshots id="3002" project_id="1002" root_project_id="1001" parent_snapshot_id="3001" root_snapshot_id="3001"
scope="PRJ" qualifier="BRC" created_at="2010-12-25 00:00:00.00" version="[null]" path="3001."
status="U" islast="false" depth="1" />

<snapshots id="3003" project_id="1003" root_project_id="1001" parent_snapshot_id="3001" root_snapshot_id="3001"
scope="PRJ" qualifier="BRC" created_at="2010-12-25 00:00:00.00" version="[null]" path="3001."
status="U" islast="false" depth="1" />

<snapshots id="3004" project_id="1004" root_project_id="1001" parent_snapshot_id="3003" root_snapshot_id="3001"
scope="PRJ" qualifier="BRC" created_at="2010-12-25 00:00:00.00" version="[null]" path="3001.3003."
status="U" islast="false" depth="2" />


</dataset>

+ 22
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldSaveNewProject-result.xml View File

@@ -0,0 +1,22 @@
<dataset>

<!-- other project -->
<projects id="1000" scope="PRJ" qualifier="TRK" kee="my:key" root_id="[null]"
name="Other project" long_name="Other" description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3000" project_id="1000" parent_snapshot_id="[null]" root_project_id="1000" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2008-11-01 13:58:00.00" version="[null]" path=""
status="P" islast="false" depth="0" />


<!-- new project -->
<projects id="1001" scope="PRJ" qualifier="TRK" kee="foo" root_id="[null]"
name="Foo" long_name="Foo" description="some description"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3001" project_id="1001" parent_snapshot_id="[null]" root_project_id="1001" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-25 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0" />

</dataset>

+ 17
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldUpdateExistingResource-result.xml View File

@@ -0,0 +1,17 @@
<dataset>

<projects id="1001" scope="PRJ" qualifier="TRK" kee="foo" root_id="[null]"
name="new name" long_name="new name" description="new description"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<!-- old snapshot -->
<snapshots id="3001" project_id="1001" parent_snapshot_id="[null]" root_project_id="1001" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-23 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0" />

<!-- new snapshot -->
<snapshots id="3002" project_id="1001" parent_snapshot_id="[null]" root_project_id="1001" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-25 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0" />

</dataset>

+ 11
- 0
sonar-batch/src/test/resources/org/sonar/batch/index/ResourcePersisterTest/shouldUpdateExistingResource.xml View File

@@ -0,0 +1,11 @@
<dataset>

<projects id="1001" scope="PRJ" qualifier="TRK" kee="foo" root_id="[null]"
name="old name" long_name="old name" description="old description"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots id="3001" project_id="1001" parent_snapshot_id="[null]" root_project_id="1001" root_snapshot_id="[null]"
scope="PRJ" qualifier="TRK" created_at="2010-12-23 00:00:00.00" version="[null]" path=""
status="U" islast="false" depth="0" />

</dataset>

+ 0
- 23
sonar-batch/src/test/resources/org/sonar/batch/indexer/DefaultPersisterTest/createResource-result.xml View File

@@ -1,23 +0,0 @@
<dataset>

<projects long_name="My project" id="5" scope="PRJ" qualifier="TRK" kee="my:key"
name="My project" root_id="[null]"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects long_name="org.foo" id="6" scope="DIR" qualifier="PAC" kee="my:key:org.foo"
name="org.foo" root_id="5"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>



<snapshots depth="0" id="30" scope="PRJ" qualifier="TRK" created_at="2008-11-01 13:58:00.00" version="[null]"
project_id="5" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="U" islast="false"
path=""/>

<snapshots depth="1" id="31" scope="DIR" qualifier="PAC" created_at="2008-11-01 13:58:00.00" version="[null]"
project_id="6" parent_snapshot_id="30" root_project_id="5" root_snapshot_id="30" status="U" islast="false"
path="30."/>

</dataset>

+ 0
- 12
sonar-batch/src/test/resources/org/sonar/batch/indexer/DefaultPersisterTest/createResource.xml View File

@@ -1,12 +0,0 @@
<dataset>

<projects long_name="My project" id="5" scope="PRJ" qualifier="TRK" kee="my:key"
name="My project" root_id="[null]"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<snapshots depth="0" id="30" scope="PRJ" qualifier="TRK" created_at="2008-11-01 13:58:00.00" version="[null]"
project_id="5" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="U" islast="false"
path=""/>

</dataset>

+ 0
- 23
sonar-batch/src/test/resources/org/sonar/batch/indexer/DefaultPersisterTest/updateExistingResource-result.xml View File

@@ -1,23 +0,0 @@
<dataset>

<projects long_name="My project" id="5" scope="PRJ" qualifier="TRK" kee="my:key"
name="My project" root_id="[null]"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects long_name="org.foo" id="6" scope="DIR" qualifier="PAC" kee="my:key:org.foo"
name="org.foo" root_id="5"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>



<snapshots depth="0" id="30" scope="PRJ" qualifier="TRK" created_at="2008-11-01 13:58:00.00" version="[null]"
project_id="5" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="U" islast="false"
path=""/>

<snapshots depth="1" id="31" scope="DIR" qualifier="PAC" created_at="2008-11-01 13:58:00.00" version="[null]"
project_id="6" parent_snapshot_id="30" root_project_id="5" root_snapshot_id="30" status="U" islast="false"
path="30."/>

</dataset>

+ 0
- 18
sonar-batch/src/test/resources/org/sonar/batch/indexer/DefaultPersisterTest/updateExistingResource.xml View File

@@ -1,18 +0,0 @@
<dataset>

<projects long_name="My project" id="5" scope="PRJ" qualifier="TRK" kee="my:key"
name="My project" root_id="[null]"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>

<projects long_name="org.foo" id="6" scope="DIR" qualifier="PAC" kee="my:key:org.foo"
name="org.foo" root_id="[null]"
description="[null]"
enabled="true" language="java" copy_resource_id="[null]" profile_id="[null]"/>


<snapshots depth="0" id="30" scope="PRJ" qualifier="TRK" created_at="2008-11-01 13:58:00.00" version="[null]"
project_id="5" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]" status="U" islast="false"
path=""/>

</dataset>

+ 0
- 23
sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/addNewLibraryVersion-result.xml View File

@@ -1,23 +0,0 @@
<dataset>

<projects long_name="my project" id="1" scope="PRJ" kee="my:project" qualifier="TRK" name="my project"
root_id="[null]"
description="[null]" enabled="true" profile_id="[null]" language="java" copy_resource_id="[null]"/>

<projects long_name="Commons Lang" id="2" scope="PRJ" kee="commons-lang:commons-lang" qualifier="LIB" name="Commons Lang"
root_id="[null]"
description="[null]" enabled="true" profile_id="[null]" language="[null]" copy_resource_id="[null]"/>

<snapshots id="1" created_at="2008-12-25 00:00:00.00" version="1.0" project_id="1" scope="PRJ" qualifier="TRK"
root_project_id="1" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="U" ISLAST="false"
path="" depth="0"/>

<snapshots id="2" created_at="2010-05-18 17:00:00.00" version="1.1" project_id="2" scope="PRJ" qualifier="LIB"
root_project_id="2" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="P" ISLAST="false"
path="" depth="0"/>

<snapshots id="3" created_at="2010-05-18 17:00:00.00" version="1.2" project_id="2" scope="PRJ" qualifier="LIB"
root_project_id="2" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="P" ISLAST="false"
path="" depth="0"/>

</dataset>

+ 0
- 19
sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/addNewLibraryVersion.xml View File

@@ -1,19 +0,0 @@
<dataset>

<projects long_name="my project" id="1" scope="PRJ" kee="my:project" qualifier="TRK" name="my project"
root_id="[null]"
description="[null]" enabled="true" profile_id="[null]" language="java" copy_resource_id="[null]"/>

<projects long_name="Commons Lang" id="2" scope="PRJ" kee="commons-lang:commons-lang" qualifier="LIB" name="Commons Lang"
root_id="[null]"
description="[null]" enabled="true" profile_id="[null]" language="[null]" copy_resource_id="[null]"/>

<snapshots id="1" created_at="2008-12-25 00:00:00.00" version="1.0" project_id="1" scope="PRJ" qualifier="TRK"
root_project_id="1" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="U" ISLAST="false"
path="" depth="0"/>

<snapshots id="2" created_at="2010-05-18 17:00:00.00" version="1.1" project_id="2" scope="PRJ" qualifier="LIB"
root_project_id="2" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="P" ISLAST="false"
path="" depth="0"/>

</dataset>

+ 0
- 19
sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/createLibrary-result.xml View File

@@ -1,19 +0,0 @@
<dataset>

<projects long_name="my project" id="1" scope="PRJ" kee="my:project" qualifier="TRK" name="my project"
root_id="[null]"
description="[null]" enabled="true" profile_id="[null]" language="java" copy_resource_id="[null]"/>

<projects long_name="Commons Lang" id="2" scope="PRJ" kee="commons-lang:commons-lang" qualifier="LIB" name="Commons Lang"
root_id="[null]"
description="[null]" enabled="true" profile_id="[null]" language="[null]" copy_resource_id="[null]"/>

<snapshots id="1" created_at="2008-12-25 00:00:00.00" version="1.0" project_id="1" scope="PRJ" qualifier="TRK"
root_project_id="1" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="U" ISLAST="false"
path="" depth="0"/>

<snapshots id="2" created_at="2010-05-18 17:00:00.00" version="1.1" project_id="2" scope="PRJ" qualifier="LIB"
root_project_id="2" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="P" ISLAST="false"
path="" depth="0"/>

</dataset>

+ 0
- 11
sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/createLibrary.xml View File

@@ -1,11 +0,0 @@
<dataset>

<projects long_name="my project" id="1" scope="PRJ" kee="my:project" qualifier="TRK" name="my project"
root_id="[null]"
description="[null]" enabled="true" profile_id="[null]" language="java" copy_resource_id="[null]"/>

<snapshots id="1" created_at="2008-12-25 00:00:00.00" version="1.0" project_id="1" scope="PRJ" qualifier="TRK"
root_project_id="1" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="U" ISLAST="false"
path="" depth="0"/>

</dataset>

+ 0
- 19
sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/reuseExistingLibrary-result.xml View File

@@ -1,19 +0,0 @@
<dataset>

<projects long_name="my project" id="1" scope="PRJ" kee="my:project" qualifier="TRK" name="my project"
root_id="[null]"
description="[null]" enabled="true" profile_id="[null]" language="java" copy_resource_id="[null]"/>

<projects long_name="Commons Lang" id="2" scope="PRJ" kee="commons-lang:commons-lang" qualifier="LIB" name="Commons Lang"
root_id="[null]"
description="[null]" enabled="true" profile_id="[null]" language="[null]" copy_resource_id="[null]"/>

<snapshots id="1" created_at="2008-12-25 00:00:00.00" version="1.0" project_id="1" scope="PRJ" qualifier="TRK"
root_project_id="1" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="U" ISLAST="false"
path="" depth="0"/>

<snapshots id="2" created_at="[null]" version="1.1" project_id="2" scope="PRJ" qualifier="LIB"
root_project_id="2" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="P" ISLAST="false"
path="" depth="0"/>

</dataset>

+ 0
- 19
sonar-batch/src/test/resources/org/sonar/batch/indexer/LibraryPersisterTest/reuseExistingLibrary.xml View File

@@ -1,19 +0,0 @@
<dataset>

<projects long_name="my project" id="1" scope="PRJ" kee="my:project" qualifier="TRK" name="my project"
root_id="[null]"
description="[null]" enabled="true" profile_id="[null]" language="java" copy_resource_id="[null]"/>

<projects long_name="Commons Lang" id="2" scope="PRJ" kee="commons-lang:commons-lang" qualifier="LIB" name="Commons Lang"
root_id="[null]"
description="[null]" enabled="true" profile_id="[null]" language="[null]" copy_resource_id="[null]"/>

<snapshots id="1" created_at="2008-12-25 00:00:00.00" version="1.0" project_id="1" scope="PRJ" qualifier="TRK"
root_project_id="1" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="U" ISLAST="false"
path="" depth="0"/>

<snapshots id="2" created_at="[null]" version="1.1" project_id="2" scope="PRJ" qualifier="LIB"
root_project_id="2" root_snapshot_id="[null]" parent_snapshot_id="[null]" STATUS="P" ISLAST="false"
path="" depth="0"/>

</dataset>

+ 19
- 0
sonar-batch/src/test/resources/org/sonar/batch/phases/MavenPluginsConfiguratorTest/pom.xml View File

@@ -0,0 +1,19 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mygroup</groupId>
<artifactId>myartifact</artifactId>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.2</version>
<configuration>
<outputFileFormat>html</outputFileFormat>
</configuration>
</plugin>
</plugins>
</build>
</project>

+ 1
- 1
sonar-core/src/main/java/org/sonar/jpa/dao/AsyncMeasuresDao.java View File

@@ -131,7 +131,7 @@ public class AsyncMeasuresDao extends BaseDao {
"AND ams.snapshotDate>=:measureDate " +
"ORDER BY ams.snapshotDate ASC ")
.setParameter("projectId", asyncMeasure.getProjectId())
.setParameter("metricId", asyncMeasure.getMetric().getId())
.setParameter("metricId", asyncMeasure.getMetricId())
.setParameter("measureDate", asyncMeasure.getMeasureDate());
if (endDate != null) {
query.setParameter("endDate", endDate);

+ 5
- 5
sonar-core/src/main/java/org/sonar/jpa/dao/AsyncMeasuresService.java View File

@@ -90,7 +90,7 @@ public class AsyncMeasuresService {
AsyncMeasuresDao dao = new AsyncMeasuresDao(session);
MeasureModel measure = dao.getAsyncMeasure(id);
AsyncMeasureSnapshot pastAsyncMeasureSnapshot = dao.getLastAsyncMeasureSnapshot(measure.getProjectId(),
measure.getMetric().getId(), measure.getMeasureDate());
measure.getMetricId(), measure.getMeasureDate());
dao.deleteAsyncMeasure(measure);
if (pastAsyncMeasureSnapshot != null) {
MeasureModel pastAsyncMeasure = dao.getAsyncMeasure(pastAsyncMeasureSnapshot.getMeasureId());
@@ -102,7 +102,7 @@ public class AsyncMeasuresService {

private void registerMeasure(MeasureModel measure, AsyncMeasuresDao dao) {
AsyncMeasureSnapshot nextAsyncMeasureSnapshot = dao.getNextAsyncMeasureSnapshot(
measure.getProjectId(), measure.getMetric().getId(), measure.getMeasureDate());
measure.getProjectId(), measure.getMetricId(), measure.getMeasureDate());
Date dateNextAsyncMeasure = (nextAsyncMeasureSnapshot != null) ? nextAsyncMeasureSnapshot.getMeasureDate() : null;

List<AsyncMeasureSnapshot> nextAsyncMeasureSnapshots = dao.getNextAsyncMeasureSnapshotsUntilDate(
@@ -110,7 +110,7 @@ public class AsyncMeasuresService {
if (!nextAsyncMeasureSnapshots.isEmpty()) {
for (AsyncMeasureSnapshot asyncMeasureSnapshot : nextAsyncMeasureSnapshots) {
dao.createAsyncMeasureSnapshot(measure.getId(), asyncMeasureSnapshot.getSnapshotId(), measure.getMeasureDate(),
asyncMeasureSnapshot.getSnapshotDate(), measure.getMetric().getId(), measure.getProjectId());
asyncMeasureSnapshot.getSnapshotDate(), measure.getMetricId(), measure.getProjectId());
dao.removeSnapshotFromAsyncMeasureSnapshot(asyncMeasureSnapshot);
}
} else {
@@ -118,11 +118,11 @@ public class AsyncMeasuresService {
if (!nextSnapshotsUntilDate.isEmpty()) {
for (Snapshot nextSnapshot : nextSnapshotsUntilDate) {
dao.createAsyncMeasureSnapshot(measure.getId(), nextSnapshot.getId(), measure.getMeasureDate(),
nextSnapshot.getCreatedAt(), measure.getMetric().getId(), measure.getProjectId());
nextSnapshot.getCreatedAt(), measure.getMetricId(), measure.getProjectId());
}
} else {
dao.createAsyncMeasureSnapshot(measure.getId(), null, measure.getMeasureDate(),
null, measure.getMetric().getId(), measure.getProjectId());
null, measure.getMetricId(), measure.getProjectId());
}
}
}

+ 4
- 2
sonar-core/src/test/java/org/sonar/jpa/session/DatabaseSessionTest.java View File

@@ -26,6 +26,7 @@ import org.junit.internal.matchers.IsCollectionContaining;
import org.sonar.api.database.model.MeasureModel;
import org.sonar.api.database.model.ResourceModel;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.jpa.dao.MeasuresDao;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
@@ -53,11 +54,12 @@ public class DatabaseSessionTest extends AbstractDbUnitTestCase {
Snapshot snapshot = new Snapshot(project1, true, "", new Date(1));
getSession().save(project1, snapshot);
getSession().save(CoreMetrics.CLASSES);
getSession().commit();
Metric metric = new MeasuresDao(getSession()).getMetric("classes_count");
Metric metric = new MeasuresDao(getSession()).getMetric(CoreMetrics.CLASSES_KEY);
for (int i = 0; i < NB_INSERTS; i++) {
MeasureModel pm = new MeasureModel(metric, 1.0).setSnapshotId(snapshot.getId());
MeasureModel pm = new MeasureModel(metric.getId(), 1.0).setSnapshotId(snapshot.getId());
getSession().save(pm);
}

+ 8
- 0
sonar-plugin-api/src/main/java/org/sonar/api/batch/Event.java View File

@@ -63,6 +63,13 @@ public class Event extends BaseIdentifiable {
public Event() {
}

public Event(String name, String description, String category) {
this.name = name;
this.description = description;
this.category = category;
}

@Deprecated
public Event(String name, String description, String category, Date date, Integer resourceId) {
this.name = name;
this.description = description;
@@ -71,6 +78,7 @@ public class Event extends BaseIdentifiable {
this.resourceId = resourceId;
}

@Deprecated
public Event(String name, String description, String category, Snapshot snapshot) {
this.name = name;
this.description = description;

+ 4
- 6
sonar-plugin-api/src/main/java/org/sonar/api/batch/SonarIndex.java View File

@@ -36,8 +36,6 @@ import java.util.Set;

public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Dependency> {

public abstract Project getRootProject();

public abstract Project getProject();

public abstract Resource getResource(Resource resource);
@@ -58,13 +56,13 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe

public abstract void addViolation(Violation violation);

public abstract Measure saveMeasure(Resource resource, Measure measure);
public abstract Measure addMeasure(Resource resource, Measure measure);

public abstract Dependency saveDependency(Dependency dependency);
public abstract Dependency addDependency(Dependency dependency);

public abstract Set<Dependency> getDependencies();

public abstract void saveLink(ProjectLink link);
public abstract void addLink(ProjectLink link);

public abstract void deleteLink(String key);

@@ -72,7 +70,7 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe

public abstract void deleteEvent(Event event);

public abstract Event createEvent(Resource resource, String name, String description, String category, Date date);
public abstract Event addEvent(Resource resource, String name, String description, String category, Date date);

public final Collection<Dependency> getOutgoingDependencies(Resource from) {
return getOutgoingEdges(from);

+ 24
- 0
sonar-plugin-api/src/main/java/org/sonar/api/batch/TimeMachineQuery.java View File

@@ -19,6 +19,7 @@
*/
package org.sonar.api.batch;

import com.google.common.collect.Lists;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.sonar.api.measures.Metric;
import org.sonar.api.resources.Resource;
@@ -39,6 +40,7 @@ public class TimeMachineQuery {

private Resource resource;
private List<Metric> metrics;
private List<String> metricKeys;
private Date from;
private Date to;
private boolean onlyLastAnalysis = false;
@@ -89,6 +91,24 @@ public class TimeMachineQuery {
*/
public TimeMachineQuery setMetrics(List<Metric> metrics) {
this.metrics = metrics;
this.metricKeys = Lists.newLinkedList();
for (Metric metric : this.metrics) {
this.metricKeys.add(metric.getKey());
}
return this;
}

public TimeMachineQuery setMetricKeys(String... metricKeys) {
this.metricKeys = Arrays.asList(metricKeys);
return this;
}

public List<String> getMetricKeys() {
return metricKeys;
}

public TimeMachineQuery setMetricKeys(List<String> metricKeys) {
this.metricKeys = metricKeys;
return this;
}

@@ -100,6 +120,10 @@ public class TimeMachineQuery {
*/
public TimeMachineQuery setMetrics(Metric... metrics) {
this.metrics = Arrays.asList(metrics);
this.metricKeys = Lists.newLinkedList();
for (Metric metric : this.metrics) {
this.metricKeys.add(metric.getKey());
}
return this;
}


+ 20
- 81
sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureModel.java View File

@@ -58,10 +58,8 @@ public class MeasureModel implements Cloneable {
@Column(name = "tendency", updatable = true, nullable = true)
private Integer tendency;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "metric_id")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
private Metric metric;
@Column(name = "metric_id", updatable = false, nullable = false)
private Integer metricId;

@Column(name = "snapshot_id", updatable = true, nullable = true)
private Integer snapshotId;
@@ -124,19 +122,19 @@ public class MeasureModel implements Cloneable {
/**
* Creates a measure based on a metric and a double value
*/
public MeasureModel(Metric metric, Double val) {
public MeasureModel(int metricId, Double val) {
if (val.isNaN() || val.isInfinite()) {
throw new IllegalArgumentException("Measure value is NaN. Metric=" + metric);
throw new IllegalArgumentException("Measure value is NaN. Metric=" + metricId);
}
this.metric = metric;
this.metricId = metricId;
this.value = val;
}

/**
* Creates a measure based on a metric and an alert level
*/
public MeasureModel(Metric metric, Metric.Level level) {
this.metric = metric;
public MeasureModel(int metricId, Metric.Level level) {
this.metricId = metricId;
if (level != null) {
this.textValue = level.toString();
}
@@ -145,8 +143,8 @@ public class MeasureModel implements Cloneable {
/**
* Creates a measure based on a metric and a string value
*/
public MeasureModel(Metric metric, String val) {
this.metric = metric;
public MeasureModel(int metricId, String val) {
this.metricId = metricId;
setData(val);
}

@@ -238,18 +236,12 @@ public class MeasureModel implements Cloneable {
return this;
}

/**
* @return the measure metric
*/
public Metric getMetric() {
return metric;
public Integer getMetricId() {
return metricId;
}

/**
* Sets the measure metric
*/
public void setMetric(Metric metric) {
this.metric = metric;
public void setMetricId(Integer metricId) {
this.metricId = metricId;
}

/**
@@ -375,7 +367,7 @@ public class MeasureModel implements Cloneable {
/**
* @return the measure data
*/
public String getData() {
public String getData(Metric metric) {
if (this.textValue != null) {
return this.textValue;
}
@@ -457,7 +449,7 @@ public class MeasureModel implements Cloneable {
public String toString() {
return new ToStringBuilder(this).
append("value", value).
append("metric", metric).
append("metricId", metricId).
toString();
}

@@ -519,7 +511,6 @@ public class MeasureModel implements Cloneable {
* @return the current object
*/
public MeasureModel save(DatabaseSession session) {
this.metric = session.reattach(Metric.class, metric.getId());
MeasureData data = getMeasureData();
setMeasureData(null);
session.save(this);
@@ -545,7 +536,7 @@ public class MeasureModel implements Cloneable {
@Override
public Object clone() {
MeasureModel clone = new MeasureModel();
clone.setMetric(getMetric());
clone.setMetricId(getMetricId());
clone.setDescription(getDescription());
clone.setTextValue(getTextValue());
clone.setAlertStatus(getAlertStatus());
@@ -580,57 +571,20 @@ public class MeasureModel implements Cloneable {
getUrl()!=null;
}


/**
* Builds a MeasureModel from a Measure
*/
public static MeasureModel build(Measure measure) {
return build(measure, new MeasureModel());
}

/**
* Merges a Measure into a MeasureModel
*/
public static MeasureModel build(Measure measure, MeasureModel merge) {
merge.setMetric(measure.getMetric());
merge.setDescription(measure.getDescription());
merge.setData(measure.getData());
merge.setAlertStatus(measure.getAlertStatus());
merge.setAlertText(measure.getAlertText());
merge.setTendency(measure.getTendency());
merge.setDiffValue1(measure.getDiffValue1());
merge.setDiffValue2(measure.getDiffValue2());
merge.setDiffValue3(measure.getDiffValue3());
merge.setUrl(measure.getUrl());
merge.setCharacteristic(measure.getCharacteristic());
if (measure.getValue() != null) {
merge.setValue(measure.getValue().doubleValue());
} else {
merge.setValue(null);
}
if (measure instanceof RuleMeasure) {
RuleMeasure ruleMeasure = (RuleMeasure) measure;
merge.setRulesCategoryId(ruleMeasure.getRuleCategory());
merge.setRulePriority(ruleMeasure.getRulePriority());
merge.setRule(ruleMeasure.getRule());
}
return merge;
}

/**
* @return a measure from the current object
*/
public Measure toMeasure() {
public Measure toMeasure(Metric metric) {
Measure measure;
if (isRuleMeasure()) {
measure = new RuleMeasure(getMetric(), getRule(), getRulePriority(), getRulesCategoryId());
measure = new RuleMeasure(metric, getRule(), getRulePriority(), getRulesCategoryId());
} else {
measure = new Measure(getMetric());
measure = new Measure(metric);
}
measure.setId(getId());
measure.setDescription(getDescription());
measure.setValue(getValue());
measure.setData(getData());
measure.setData(getData(metric));
measure.setAlertStatus(getAlertStatus());
measure.setAlertText(getAlertText());
measure.setTendency(getTendency());
@@ -641,19 +595,4 @@ public class MeasureModel implements Cloneable {
measure.setCharacteristic(getCharacteristic());
return measure;
}

/**
* Transforms a list of MeasureModel into a list of Measure
*
* @return an empty list if models is null
*/
public static List<Measure> toMeasures(List<MeasureModel> models) {
List<Measure> result = new ArrayList<Measure>();
for (MeasureModel model : models) {
if (model != null) {
result.add(model.toMeasure());
}
}
return result;
}
}

+ 6
- 16
sonar-plugin-api/src/main/java/org/sonar/api/database/model/RuleFailureModel.java View File

@@ -38,9 +38,8 @@ public class RuleFailureModel extends BaseIdentifiable {
@Column(name = "snapshot_id")
protected Integer snapshotId;

@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "rule_id")
private Rule rule;
@Column(name = "rule_id", updatable = false, nullable = false)
private Integer ruleId;

@Column(name = "failure_level", updatable = false, nullable = false)
@Enumerated(EnumType.ORDINAL)
@@ -55,15 +54,6 @@ public class RuleFailureModel extends BaseIdentifiable {
@Column(name = "cost", updatable = true, nullable = true)
private Double cost;

public RuleFailureModel() {
}

public RuleFailureModel(Rule rule, RulePriority priority) {
this.rule = rule;
this.priority = priority;
}


public String getMessage() {
return message;
}
@@ -80,12 +70,12 @@ public class RuleFailureModel extends BaseIdentifiable {
this.priority = priority;
}

public Rule getRule() {
return rule;
public Integer getRuleId() {
return ruleId;
}

public void setRule(Rule rule) {
this.rule = rule;
public void setRuleId(Integer ruleId) {
this.ruleId = ruleId;
}

public Integer getLine() {

+ 19
- 25
sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java View File

@@ -41,6 +41,7 @@ public class Measure {
public final static int DEFAULT_PRECISION = 1;

private Long id; // for internal use
protected String metricKey;
protected Metric metric;
protected Double value;
protected String data;
@@ -54,6 +55,10 @@ public class Measure {
protected Characteristic characteristic;
protected PersistenceMode persistenceMode = PersistenceMode.FULL;

public Measure(String metricKey) {
this.metricKey = metricKey;
}

/**
* Creates a measure with a metric
*
@@ -61,6 +66,7 @@ public class Measure {
*/
public Measure(Metric metric) {
this.metric = metric;
this.metricKey = metric.getKey();
}

/**
@@ -71,6 +77,7 @@ public class Measure {
*/
public Measure(Metric metric, Double value) {
this.metric = metric;
this.metricKey = metric.getKey();
setValue(value);
}

@@ -83,6 +90,7 @@ public class Measure {
*/
public Measure(Metric metric, Double value, int precision) {
this.metric = metric;
this.metricKey = metric.getKey();
setValue(value, precision);
}

@@ -95,6 +103,7 @@ public class Measure {
*/
public Measure(Metric metric, Double value, String data) {
this.metric = metric;
this.metricKey = metric.getKey();
setValue(value);
setData(data);
}
@@ -107,6 +116,7 @@ public class Measure {
*/
public Measure(Metric metric, String data) {
this.metric = metric;
this.metricKey = metric.getKey();
setData(data);
}

@@ -118,6 +128,7 @@ public class Measure {
*/
public Measure(Metric metric, Metric.Level level) {
this.metric = metric;
this.metricKey = metric.getKey();
if (level != null) {
this.data = level.toString();
}
@@ -159,6 +170,10 @@ public class Measure {
return metric;
}

public String getMetricKey() {
return metricKey;
}

/**
* Set the underlying metric
*
@@ -167,6 +182,7 @@ public class Measure {
*/
public Measure setMetric(Metric metric) {
this.metric = metric;
this.metricKey = metric.getKey();
return this;
}

@@ -474,28 +490,6 @@ public class Measure {
}


// @Override
// public boolean equals(Object obj) {
// if (!(obj.getClass().equals(Measure.class))) {
// return false;
// }
// if (this == obj) {
// return true;
// }
// Measure rhs = (Measure) obj;
// return new EqualsBuilder()
// .append(metric, rhs.getMetric())
// .append(characteristic, rhs.getCharacteristic())
// .isEquals();
// }
//
// @Override
// public int hashCode() {
// return (metric != null ? metric.hashCode() : 0);
// }
//


@Override
public boolean equals(Object o) {
if (this == o) {
@@ -506,7 +500,7 @@ public class Measure {
}

Measure measure = (Measure) o;
if (metric != null ? !metric.equals(measure.metric) : measure.metric != null) {
if (metricKey != null ? !metricKey.equals(measure.metricKey) : measure.metricKey != null) {
return false;
}
if (characteristic != null ? !characteristic.equals(measure.characteristic) : measure.characteristic != null) {
@@ -517,7 +511,7 @@ public class Measure {

@Override
public int hashCode() {
int result = metric != null ? metric.hashCode() : 0;
int result = metricKey != null ? metricKey.hashCode() : 0;
result = 31 * result + (characteristic != null ? characteristic.hashCode() : 0);
return result;
}
@@ -526,7 +520,7 @@ public class Measure {
public String toString() {
return new ToStringBuilder(this).
append("id", id).
append("metric", metric).
append("metric", metricKey).
append("value", value).
append("data", data).
append("description", description).

+ 6
- 6
sonar-plugin-api/src/main/java/org/sonar/api/measures/MeasuresFilters.java View File

@@ -52,7 +52,7 @@ public final class MeasuresFilters {
}
for (Measure measure : measures) {
if (measure.getClass().equals(Measure.class) &&
measure.getMetric().equals(metric) &&
measure.getMetricKey().equals(metric.getKey()) &&
measure.getCharacteristic()==null) {
return measure;
}
@@ -165,14 +165,14 @@ public final class MeasuresFilters {
* Used for internal optimizations.
*/
public static abstract class MetricFilter<M> implements MeasuresFilter<M> {
private final Metric metric;
private final String metricKey;

protected MetricFilter(Metric metric) {
this.metric = metric;
this.metricKey = metric.getKey();
}

public Metric filterOnMetric() {
return metric;
public String filterOnMetricKey() {
return metricKey;
}
}

@@ -183,7 +183,7 @@ public final class MeasuresFilters {

private boolean apply(Measure measure) {
return measure instanceof RuleMeasure
&& filterOnMetric().equals(measure.getMetric())
&& filterOnMetricKey().equals(measure.getMetricKey())
&& doApply((RuleMeasure) measure);
}


sonar-batch/src/main/java/org/sonar/batch/CoreJobs.java → sonar-plugin-api/src/main/java/org/sonar/api/measures/MetricFinder.java View File

@@ -17,27 +17,23 @@
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.batch;
package org.sonar.api.measures;

import java.util.ArrayList;
import org.sonar.api.BatchComponent;

import java.util.Collection;
import java.util.List;

/**
* Core batch extensions, instanciated by picocontainer.
* This component is currently available only on batch-side
*
* @since 2.5
*/
public final class CoreJobs {
public interface MetricFinder extends BatchComponent {

Metric find(String key);

private CoreJobs() {
}
Collection<Metric> findAll(List<String> metricKeys);

public static List<Class<? extends CoreJob>> allJobs() {
List<Class<? extends CoreJob>> classes = new ArrayList<Class<? extends CoreJob>>();
classes.add(MavenPluginsConfigurator.class);
classes.add(MavenPhaseExecutor.class);
classes.add(SensorsExecutor.class);
classes.add(DecoratorsExecutor.class);
classes.add(FinalizeSnapshotsJob.class);
classes.add(PostJobsExecutor.class);
return classes;
}
Collection<Metric> findAll();
}

+ 1
- 5
sonar-plugin-api/src/main/java/org/sonar/api/rules/Violation.java View File

@@ -119,12 +119,8 @@ public class Violation {
}

/**
* Sets the violation priority
*
* @return the current object
* @deprecated since 2.3. The priority is set by the quality profile.
* For internal use only
*/
@Deprecated
public Violation setPriority(RulePriority priority) {
this.priority = priority;
return this;

+ 43
- 43
sonar-plugin-api/src/test/java/org/sonar/api/database/model/MeasureModelTest.java View File

@@ -1,43 +1,43 @@
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar 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.
*
* Sonar 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 Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.api.database.model;
import org.junit.Test;
import static org.junit.Assert.assertThat;
import org.sonar.api.measures.CoreMetrics;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
public class MeasureModelTest {
@Test
public void doNotCopyDataWhenCloning() {
MeasureModel initial = new MeasureModel();
initial.setMetric(CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION);
initial.setMeasureData(new MeasureData(initial, "foo"));
initial.setValue(30.0);
assertThat(initial.getData(), is("foo"));
MeasureModel clone = (MeasureModel) initial.clone();
assertThat(clone.getData(), nullValue());
assertThat(clone.getValue(), is(30.0));
assertThat(clone.getMetric(), is(CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION));
}
}
///*
// * Sonar, open source software quality management tool.
// * Copyright (C) 2009 SonarSource SA
// * mailto:contact AT sonarsource DOT com
// *
// * Sonar 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.
// *
// * Sonar 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 Sonar; if not, write to the Free Software
// * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
// */
//package org.sonar.api.database.model;
//
//import org.junit.Test;
//import static org.junit.Assert.assertThat;
//import org.sonar.api.measures.CoreMetrics;
//import static org.hamcrest.Matchers.is;
//import static org.hamcrest.Matchers.nullValue;
//
//public class MeasureModelTest {
//
// @Test
// public void doNotCopyDataWhenCloning() {
// MeasureModel initial = new MeasureModel();
// initial.setMetric(CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION);
// initial.setMeasureData(new MeasureData(initial, "foo"));
// initial.setValue(30.0);
// assertThat(initial.getData(), is("foo"));
//
// MeasureModel clone = (MeasureModel) initial.clone();
// assertThat(clone.getData(), nullValue());
// assertThat(clone.getValue(), is(30.0));
// assertThat(clone.getMetric(), is(CoreMetrics.CLASS_COMPLEXITY_DISTRIBUTION));
// }
//}

+ 7
- 7
sonar-plugin-api/src/test/java/org/sonar/api/measures/AverageComplexityFormulaTest.java View File

@@ -19,12 +19,11 @@
*/
package org.sonar.api.measures;
import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.resources.JavaFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static junit.framework.Assert.assertNull;
@@ -41,12 +40,13 @@ public class AverageComplexityFormulaTest {
@Before
public void before() {
context = mock(FormulaContext.class);
when(context.getTargetMetric()).thenReturn(CoreMetrics.FUNCTION_COMPLEXITY);
data = mock(FormulaData.class);
}
@Test
public void testAverageCalculation() {
List<FormulaData> childrenData = new ArrayList<FormulaData>();
List<FormulaData> childrenData = Lists.newArrayList();
FormulaData data1 = mock(FormulaData.class);
childrenData.add(data1);
when(data1.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 43.0));
@@ -66,7 +66,7 @@ public class AverageComplexityFormulaTest {
@Test
public void testWhenNoChildrenMesaures() {
List<FormulaData> childrenData = new ArrayList<FormulaData>();
List<FormulaData> childrenData = Lists.newArrayList();
when(data.getChildren()).thenReturn(childrenData);
Measure measure = new AverageComplexityFormula(CoreMetrics.FUNCTIONS).calculate(data, context);
assertNull(measure);
@@ -74,7 +74,7 @@ public class AverageComplexityFormulaTest {
@Test
public void testWhenNoComplexityMesaures() {
List<FormulaData> childrenData = new ArrayList<FormulaData>();
List<FormulaData> childrenData = Lists.newArrayList();
FormulaData data1 = mock(FormulaData.class);
childrenData.add(data1);
when(data1.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 43.0));
@@ -87,7 +87,7 @@ public class AverageComplexityFormulaTest {
@Test
public void testWhenNoByMetricMesaures() {
List<FormulaData> childrenData = new ArrayList<FormulaData>();
List<FormulaData> childrenData = Lists.newArrayList();
FormulaData data1 = mock(FormulaData.class);
childrenData.add(data1);
when(data1.getMeasure(CoreMetrics.COMPLEXITY)).thenReturn(new Measure(CoreMetrics.COMPLEXITY, 43.0));
@@ -100,7 +100,7 @@ public class AverageComplexityFormulaTest {
@Test
public void testWhenMixedMetrics() {
List<FormulaData> childrenData = new ArrayList<FormulaData>();
List<FormulaData> childrenData = Lists.newArrayList();
FormulaData data1 = mock(FormulaData.class);
childrenData.add(data1);
when(data1.getMeasure(CoreMetrics.FUNCTIONS)).thenReturn(new Measure(CoreMetrics.FUNCTIONS, 43.0));

+ 2
- 2
sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureUtilsTest.java View File

@@ -34,8 +34,8 @@ public class MeasureUtilsTest {
public void getValue() {
assertThat(MeasureUtils.getValue(null, 3.0), is(3.0));
assertThat(MeasureUtils.getValue(new Measure(), 3.0), is(3.0));
assertThat(MeasureUtils.getValue(new Measure(null, 2.0), 3.0), is(2.0));
assertThat(MeasureUtils.getValue(new Measure(null, "data"), 3.0), is(3.0));
assertThat(MeasureUtils.getValue(new Measure(CoreMetrics.LINES, 2.0), 3.0), is(2.0));
assertThat(MeasureUtils.getValue(new Measure(CoreMetrics.LINES, "data"), 3.0), is(3.0));
}

@Test

+ 2
- 1
sonar-server/src/main/webapp/WEB-INF/app/models/snapshot.rb View File

@@ -65,8 +65,9 @@ class Snapshot < ActiveRecord::Base
snapshots=snapshots[-5,5] if snapshots.size>=5

snapshots.insert(0, Snapshot.find(:first,
:conditions => ["project_id=? AND status IN (?) AND scope=? AND qualifier=?", resource.id, STATUS_PROCESSED, resource.scope, resource.qualifier],
:conditions => ["project_id=? AND status=? AND scope=? AND qualifier=?", resource.id, STATUS_PROCESSED, resource.scope, resource.qualifier],
:include => 'project', :order => 'snapshots.created_at ASC', :limit => 1))

snapshots.compact.uniq
end


Loading…
Cancel
Save