diff options
16 files changed, 300 insertions, 20 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/Batch.java b/sonar-batch/src/main/java/org/sonar/batch/Batch.java index 36a702073cd..c2b15adda09 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/Batch.java +++ b/sonar-batch/src/main/java/org/sonar/batch/Batch.java @@ -19,9 +19,6 @@ */ package org.sonar.batch; -import java.net.URLClassLoader; -import java.util.Arrays; - import org.apache.commons.configuration.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -43,6 +40,9 @@ import org.sonar.jpa.session.DatabaseSessionProvider; import org.sonar.jpa.session.DriverDatabaseConnector; import org.sonar.jpa.session.ThreadLocalDatabaseSessionFactory; +import java.net.URLClassLoader; +import java.util.Arrays; + public class Batch { private static final Logger LOG = LoggerFactory.getLogger(Batch.class); @@ -89,6 +89,7 @@ public class Batch { addComponent(EventPersister.class); addComponent(LinkPersister.class); addComponent(MeasurePersister.class); + addComponent(MemoryOptimizer.class); addComponent(DefaultResourcePersister.class); addComponent(SourcePersister.class); addComponent(ViolationPersister.class); diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java index 5272ab80cb1..dedee60406a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java +++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultDecoratorContext.java @@ -19,6 +19,7 @@ */ package org.sonar.batch; +import com.google.common.collect.Lists; import org.sonar.api.batch.DecoratorContext; import org.sonar.api.batch.Event; import org.sonar.api.database.DatabaseSession; @@ -32,7 +33,10 @@ import org.sonar.api.resources.Resource; import org.sonar.api.rules.Violation; import org.sonar.batch.index.DefaultIndex; -import java.util.*; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Set; public class DefaultDecoratorContext implements DecoratorContext { @@ -79,11 +83,11 @@ public class DefaultDecoratorContext implements DecoratorContext { } public Measure getMeasure(Metric metric) { - return index.getMeasures(resource, MeasuresFilters.metric(metric)); + return index.getMeasure(resource, metric); } public Collection<Measure> getChildrenMeasures(MeasuresFilter filter) { - List<Measure> result = new ArrayList<Measure>(); + List<Measure> result = Lists.newArrayList(); for (DecoratorContext childContext : childrenContexts) { Object childResult = childContext.getMeasures(filter); if (childResult != null) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java index abafcdb150e..494e1a84997 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java @@ -19,8 +19,6 @@ */ package org.sonar.batch.index; -import java.util.*; - import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -43,6 +41,8 @@ import org.sonar.batch.ProjectTree; import org.sonar.batch.ResourceFilters; import org.sonar.batch.ViolationFilters; +import java.util.*; + public class DefaultIndex extends SonarIndex { private static final Logger LOG = LoggerFactory.getLogger(DefaultIndex.class); @@ -136,7 +136,10 @@ public class DefaultIndex extends SonarIndex { public Measure getMeasure(Resource resource, Metric metric) { Bucket bucket = buckets.get(resource); if (bucket != null) { - return bucket.getMeasures(MeasuresFilters.metric(metric)); + Measure measure = bucket.getMeasures(MeasuresFilters.metric(metric)); + if (measure!=null) { + return persistence.reloadMeasure(measure); + } } return null; } @@ -144,6 +147,7 @@ public class DefaultIndex extends SonarIndex { public <M> M getMeasures(Resource resource, MeasuresFilter<M> filter) { Bucket bucket = buckets.get(resource); if (bucket != null) { + // TODO the data measures which are not kept in memory are not reloaded yet. Use getMeasure(). return bucket.getMeasures(filter); } return null; @@ -160,13 +164,11 @@ public class DefaultIndex extends SonarIndex { throw new SonarException("Unknown metric: " + measure.getMetricKey()); } measure.setMetric(metric); - if (measure.getPersistenceMode().useMemory()) { - bucket.addMeasure(measure); - } + bucket.addMeasure(measure); + if (measure.getPersistenceMode().useDatabase()) { persistence.saveMeasure(resource, measure); } - // TODO keep database measures in cache but remove data } return measure; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultPersistenceManager.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultPersistenceManager.java index a89991610e4..f5722b7f5a2 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultPersistenceManager.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultPersistenceManager.java @@ -84,6 +84,10 @@ public final class DefaultPersistenceManager implements PersistenceManager { } } + public Measure reloadMeasure(Measure measure) { + return measurePersister.reloadMeasure(measure); + } + public void saveDependency(Project project, Dependency dependency, Dependency parentDependency) { if (ResourceUtils.isPersistable(dependency.getFrom()) && ResourceUtils.isPersistable(dependency.getTo())) { dependencyPersister.saveDependency(project, dependency, parentDependency); diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java index 97942ef8f30..e11ab691509 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/MeasurePersister.java @@ -45,11 +45,14 @@ public final class MeasurePersister { private DatabaseSession session; private ResourcePersister resourcePersister; private RuleFinder ruleFinder; + private MemoryOptimizer memoryOptimizer; - public MeasurePersister(DatabaseSession session, ResourcePersister resourcePersister, RuleFinder ruleFinder) { + + public MeasurePersister(DatabaseSession session, ResourcePersister resourcePersister, RuleFinder ruleFinder, MemoryOptimizer memoryOptimizer) { this.session = session; this.resourcePersister = resourcePersister; this.ruleFinder = ruleFinder; + this.memoryOptimizer = memoryOptimizer; } public void setDelayedMode(boolean delayedMode) { @@ -63,22 +66,30 @@ public final class MeasurePersister { } else { Snapshot snapshot = resourcePersister.getSnapshotOrFail(resource); + MeasureModel model = null; if (measure.getId() != null) { // update - MeasureModel model = session.reattach(MeasureModel.class, measure.getId()); + model = session.reattach(MeasureModel.class, measure.getId()); model = mergeModel(measure, model); model.save(session); } else if (shouldPersistMeasure(resource, measure)) { // insert - MeasureModel model = createModel(measure); + model = createModel(measure); model.setSnapshotId(snapshot.getId()); model.save(session); measure.setId(model.getId()); // could be removed } + if (model != null) { + memoryOptimizer.evictDataMeasure(measure, model); + } } } + public Measure reloadMeasure(Measure measure) { + return memoryOptimizer.reloadMeasure(measure); + } + static boolean shouldPersistMeasure(Resource resource, Measure measure) { Metric metric = measure.getMetric(); return measure.getPersistenceMode().useDatabase() && diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/MemoryOptimizer.java b/sonar-batch/src/main/java/org/sonar/batch/index/MemoryOptimizer.java new file mode 100644 index 00000000000..0fa0610d900 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/index/MemoryOptimizer.java @@ -0,0 +1,97 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * 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 org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.database.DatabaseSession; +import org.sonar.api.database.model.MeasureData; +import org.sonar.api.database.model.MeasureModel; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.PersistenceMode; + +import java.util.List; +import java.util.Map; + +/** + * @since 2.7 + */ +public class MemoryOptimizer { + + private static final Logger LOG = LoggerFactory.getLogger(MemoryOptimizer.class); + + private List<Measure> loadedMeasures = Lists.newArrayList(); + private Map<Long, Integer> dataIdByMeasureId = Maps.newHashMap(); + private DatabaseSession session; + + public MemoryOptimizer(DatabaseSession session) { + this.session = session; + } + + /** + * Remove data of a database measure from memory. + */ + public void evictDataMeasure(Measure measure, MeasureModel model) { + if (PersistenceMode.DATABASE.equals(measure.getPersistenceMode())) { + MeasureData data = model.getMeasureData(); + if (data != null && data.getId() != null) { + if (LOG.isDebugEnabled()) { + LOG.debug("Remove data measure from memory: " + measure.getMetricKey() + ", id=" + measure.getId()); + } + measure.unsetData(); + dataIdByMeasureId.put(measure.getId(), data.getId()); + } + } + } + + public Measure reloadMeasure(Measure measure) { + if (measure.getId() != null && dataIdByMeasureId.containsKey(measure.getId()) && !measure.hasData()) { + Integer dataId = dataIdByMeasureId.get(measure.getId()); + MeasureData data = session.getSingleResult(MeasureData.class, "id", dataId); + if (data == null) { + LoggerFactory.getLogger(getClass()).error("The MEASURE_DATA row with id " + dataId + " is lost"); + + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("Reload the data measure: " + measure.getMetricKey() + ", id=" + measure.getId()); + } + measure.setData(data.getText()); + loadedMeasures.add(measure); + } + } + return measure; + } + + public void flushMemory() { + if (LOG.isDebugEnabled() && loadedMeasures.size() > 0) { + LOG.debug("Flush " + loadedMeasures.size() + " data measures from memory: "); + } + for (Measure measure : loadedMeasures) { + measure.unsetData(); + } + loadedMeasures.clear(); + } + + boolean isTracked(Long measureId) { + return dataIdByMeasureId.get(measureId)!=null; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/PersistenceManager.java b/sonar-batch/src/main/java/org/sonar/batch/index/PersistenceManager.java index cef245960c9..98de69eb77f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/PersistenceManager.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/PersistenceManager.java @@ -23,7 +23,6 @@ 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.File; import org.sonar.api.resources.Project; import org.sonar.api.resources.ProjectLink; import org.sonar.api.resources.Resource; @@ -45,6 +44,8 @@ public interface PersistenceManager { void saveMeasure(Resource resource, Measure measure); + Measure reloadMeasure(Measure measure); + void saveDependency(Project project, Dependency dependency, Dependency parentDependency); void saveLink(Project project, ProjectLink link); diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java index 74b7179b16a..15532994702 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/phases/DecoratorsExecutor.java @@ -34,6 +34,7 @@ import org.sonar.api.resources.Resource; import org.sonar.batch.DecoratorsSelector; import org.sonar.batch.DefaultDecoratorContext; import org.sonar.batch.index.DefaultIndex; +import org.sonar.batch.index.MemoryOptimizer; import java.util.Collection; import java.util.IdentityHashMap; @@ -46,11 +47,14 @@ public class DecoratorsExecutor implements BatchComponent { private DatabaseSession session; private static final Logger LOG = LoggerFactory.getLogger(DecoratorsExecutor.class); private DefaultIndex index; + private MemoryOptimizer memoryOptimizer; - public DecoratorsExecutor(BatchExtensionDictionnary extensionDictionnary, DefaultIndex index, DatabaseSession session) { + public DecoratorsExecutor(BatchExtensionDictionnary extensionDictionnary, DefaultIndex index, DatabaseSession session, + MemoryOptimizer memoryOptimizer) { this.decoratorsSelector = new DecoratorsSelector(extensionDictionnary); this.session = session; this.index = index; + this.memoryOptimizer = memoryOptimizer; } @@ -81,6 +85,7 @@ public class DecoratorsExecutor implements BatchComponent { for (Decorator decorator : decorators) { profiler.start(decorator); decorator.decorate(resource, context); + memoryOptimizer.flushMemory(); profiler.stop(); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/SensorsExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/SensorsExecutor.java index 707015d2d5a..e78a56f25c7 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/SensorsExecutor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/phases/SensorsExecutor.java @@ -32,6 +32,7 @@ import org.sonar.api.database.DatabaseSession; import org.sonar.api.resources.Project; import org.sonar.api.utils.TimeProfiler; import org.sonar.batch.MavenPluginExecutor; +import org.sonar.batch.index.MemoryOptimizer; import java.util.Collection; @@ -41,11 +42,14 @@ public class SensorsExecutor implements BatchComponent { private Collection<Sensor> sensors; private DatabaseSession session; private MavenPluginExecutor mavenExecutor; + private MemoryOptimizer memoryOptimizer; - public SensorsExecutor(BatchExtensionDictionnary selector, Project project, DatabaseSession session, MavenPluginExecutor mavenExecutor) { + public SensorsExecutor(BatchExtensionDictionnary selector, Project project, DatabaseSession session, MavenPluginExecutor mavenExecutor, + MemoryOptimizer memoryOptimizer) { this.sensors = selector.select(Sensor.class, project, true); this.session = session; this.mavenExecutor = mavenExecutor; + this.memoryOptimizer = memoryOptimizer; } public void execute(Project project, SensorContext context) { @@ -58,6 +62,7 @@ public class SensorsExecutor implements BatchComponent { TimeProfiler profiler = new TimeProfiler(logger).start("Sensor " + sensor); sensor.analyse(project, context); + memoryOptimizer.flushMemory(); session.commit(); profiler.stop(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java index 81dd495a9f5..3753b6752e8 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/MeasurePersisterTest.java @@ -36,11 +36,13 @@ import org.sonar.jpa.test.AbstractDbUnitTestCase; import java.util.List; +import static org.hamcrest.CoreMatchers.anyOf; 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.verify; import static org.mockito.Mockito.when; public class MeasurePersisterTest extends AbstractDbUnitTestCase { @@ -57,6 +59,7 @@ public class MeasurePersisterTest extends AbstractDbUnitTestCase { private JavaFile aFile = new JavaFile("org.foo.Bar"); private Snapshot projectSnapshot, packageSnapshot, fileSnapshot; private Metric ncloc, coverage; + private MemoryOptimizer memoryOptimizer; @Before public void mockResourcePersister() { @@ -73,7 +76,8 @@ public class MeasurePersisterTest extends AbstractDbUnitTestCase { when(resourcePersister.getSnapshot(project)).thenReturn(projectSnapshot); when(resourcePersister.getSnapshot(aPackage)).thenReturn(packageSnapshot); when(resourcePersister.getSnapshot(aFile)).thenReturn(fileSnapshot); - measurePersister = new MeasurePersister(getSession(), resourcePersister, new DefaultRuleFinder(getSessionFactory())); + memoryOptimizer = mock(MemoryOptimizer.class); + measurePersister = new MeasurePersister(getSession(), resourcePersister, new DefaultRuleFinder(getSessionFactory()), memoryOptimizer); } @Test @@ -86,6 +90,16 @@ public class MeasurePersisterTest extends AbstractDbUnitTestCase { } @Test + public void shouldRegisterPersistedMeasureToMemoryOptimizer() { + Measure measure = new Measure(ncloc).setValue(1234.0); + + measurePersister.saveMeasure(project, measure); + + verify(memoryOptimizer).evictDataMeasure(eq(measure), (MeasureModel)anyObject()); + } + + + @Test public void shouldUpdateMeasure() { Measure measure = new Measure(coverage).setValue(12.5); measure.setId(1L); diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/MemoryOptimizerTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/MemoryOptimizerTest.java new file mode 100644 index 00000000000..6b3e0b86316 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/index/MemoryOptimizerTest.java @@ -0,0 +1,95 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * 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.hamcrest.core.IsNull; +import org.junit.Test; +import org.sonar.api.database.model.MeasureData; +import org.sonar.api.database.model.MeasureModel; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Measure; +import org.sonar.api.measures.PersistenceMode; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.core.IsNull.nullValue; +import static org.junit.Assert.assertThat; + +public class MemoryOptimizerTest extends AbstractDbUnitTestCase { + + @Test + public void shouldEvictDatabaseOnlyMeasure() { + MemoryOptimizer optimizer = new MemoryOptimizer(getSession()); + Measure measure = new Measure(CoreMetrics.CONDITIONS_BY_LINE) + .setData("10=23") + .setPersistenceMode(PersistenceMode.DATABASE) + .setId(12345L); + MeasureModel model = newPersistedModel(); + + optimizer.evictDataMeasure(measure, model); + + assertThat(optimizer.isTracked(12345L),is(true)); + assertThat(measure.getData(), nullValue());// data has been removed from memory + } + + @Test + public void shouldNotEvictStandardMeasure() { + MemoryOptimizer optimizer = new MemoryOptimizer(getSession()); + Measure measure = new Measure(CoreMetrics.PROFILE) + .setData("Sonar way") + .setId(12345L); + MeasureModel model = newPersistedModel(); + + optimizer.evictDataMeasure(measure, model); + + assertThat(optimizer.isTracked(12345L),is(false)); + assertThat(measure.getData(), is("Sonar way")); + } + + @Test + public void shouldReloadEvictedMeasure() { + setupData("shouldReloadEvictedMeasure"); + MemoryOptimizer optimizer = new MemoryOptimizer(getSession()); + Measure measure = new Measure(CoreMetrics.CONDITIONS_BY_LINE) + .setData("initial") + .setPersistenceMode(PersistenceMode.DATABASE) + .setId(12345L); + + optimizer.evictDataMeasure(measure, newPersistedModel()); + assertThat(measure.getData(), nullValue()); + + optimizer.reloadMeasure(measure); + + assertThat(measure.getData().length(), greaterThan(5)); + + optimizer.flushMemory(); + assertThat(measure.getData(), nullValue()); + } + + private MeasureModel newPersistedModel() { + MeasureModel model = new MeasureModel(); + model.setId(12345L); + MeasureData measureData = new MeasureData(); + measureData.setId(500); + model.setMeasureData(measureData); + return model; + } +} diff --git a/sonar-batch/src/test/resources/org/sonar/batch/index/MemoryOptimizerTest/shouldReloadEvictedMeasure.xml b/sonar-batch/src/test/resources/org/sonar/batch/index/MemoryOptimizerTest/shouldReloadEvictedMeasure.xml new file mode 100644 index 00000000000..5f40b829f73 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/index/MemoryOptimizerTest/shouldReloadEvictedMeasure.xml @@ -0,0 +1,8 @@ +<dataset> + + + <measure_data id="2" measure_id="2" snapshot_id="2" data="[null]"/> + <measure_data id="500" measure_id="12345" snapshot_id="1" data="value from database"/> + + +</dataset>
\ No newline at end of file diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java index 59c1f66ed9a..b33487af40f 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/CoreMetrics.java @@ -600,6 +600,7 @@ public final class CoreMetrics { // SCM + // These metrics are computed by the SCM Activity plugin, since version 1.2. public static final String SCM_COMMITS_KEY = "commits"; public static final Metric SCM_COMMITS = new Metric.Builder(SCM_COMMITS_KEY, Metric.ValueType.INT) diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java index 3b64b89da3f..6462db590d5 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Measure.java @@ -323,6 +323,14 @@ public class Measure { } /** + * @since 2.7 + */ + public Measure unsetData() { + this.data=null; + return this; + } + + /** * @return the description of the measure */ public String getDescription() { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java index 92050c92d81..e0ec08d89aa 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/Metric.java @@ -130,7 +130,9 @@ public class Metric implements ServerExtension, BatchExtension { * Creates a metric based on its key. Shortcut to Metric(key, ValueType.INT) * * @param key the metric key + * @deprecated since 2.7 use the Builder factory. */ + @Deprecated public Metric(String key) { this(key, ValueType.INT); } @@ -141,11 +143,17 @@ public class Metric implements ServerExtension, BatchExtension { * * @param key the key * @param type the type + * @deprecated since 2.7 use the Builder factory. */ + @Deprecated public Metric(String key, ValueType type) { this(key, key, key, type, -1, Boolean.FALSE, null, false); } + /** + * @deprecated since 2.7 use the Builder factory. + */ + @Deprecated public Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, String domain) { this(key, name, description, type, direction, qualitative, domain, false); } @@ -164,6 +172,7 @@ public class Metric implements ServerExtension, BatchExtension { * @param qualitative whether the metric is qualitative * @param domain the metric domain * @param userManaged whether the metric is user managed + * @deprecated since 2.7 use the Builder factory. */ @Deprecated public Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, String domain, boolean userManaged) { @@ -197,7 +206,9 @@ public class Metric implements ServerExtension, BatchExtension { * @param qualitative whether the metric is qualitative * @param domain the metric domain * @param formula the metric formula + * @deprecated since 2.7 use the Builder factory. */ + @Deprecated public Metric(String key, String name, ValueType type, Integer direction, Boolean qualitative, String domain, Formula formula) { this.key = key; this.name = name; diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureTest.java index 50f2a329574..6a29f0c1c22 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/measures/MeasureTest.java @@ -114,4 +114,17 @@ public class MeasureTest { assertFalse(measure.equals(ruleMeasure)); assertFalse(ruleMeasure.equals(measure)); } + + @Test + public void shouldUnsetData() { + String data = "1=10;21=456"; + Measure measure = new Measure(CoreMetrics.CONDITIONS_BY_LINE).setData( data); + assertThat(measure.hasData(), is(true)); + assertThat(measure.getData(), is(data)); + + measure.unsetData(); + + assertThat(measure.hasData(), is(false)); + assertThat(measure.getData(), nullValue()); + } } |