diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-06-18 00:03:18 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2015-06-18 11:52:18 +0200 |
commit | 021bf45623b748e70f20d956e86d595191241786 (patch) | |
tree | 759c5eab8fdd928cf01c3f3495ded8d968922e07 | |
parent | d370049974502061b852e73f25700c0d3bf218e6 (diff) | |
download | sonarqube-021bf45623b748e70f20d956e86d595191241786.tar.gz sonarqube-021bf45623b748e70f20d956e86d595191241786.zip |
Refactor registration of metrics at server startup
Replace Hibernate by MyBatis
31 files changed, 397 insertions, 429 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java b/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java index b4194d66178..481ca005b96 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java +++ b/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java @@ -36,6 +36,7 @@ import org.sonar.core.persistence.DbSession; import org.sonar.core.persistence.MyBatis; import org.sonar.core.properties.PropertiesDao; import org.sonar.core.purge.PurgeDao; +import org.sonar.core.qualitygate.db.QualityGateConditionDao; import org.sonar.core.qualityprofile.db.QualityProfileDao; import org.sonar.core.resource.ResourceDao; import org.sonar.core.technicaldebt.db.CharacteristicDao; @@ -107,6 +108,7 @@ public class DbClient { private final EventDao eventDao; private final PurgeDao purgeDao; private final CustomMeasureDao customMeasureDao; + private final QualityGateConditionDao gateConditionDao; public DbClient(Database db, MyBatis myBatis, DaoComponent... daoComponents) { this.db = db; @@ -150,6 +152,7 @@ public class DbClient { componentLinkDao = getDao(map, ComponentLinkDao.class); eventDao = getDao(map, EventDao.class); purgeDao = getDao(map, PurgeDao.class); + gateConditionDao = getDao(map, QualityGateConditionDao.class); } public Database database() { @@ -296,6 +299,10 @@ public class DbClient { return purgeDao; } + public QualityGateConditionDao gateConditionDao() { + return gateConditionDao; + } + private <K> K getDao(Map<Class, DaoComponent> map, Class<K> clazz) { return (K) map.get(clazz); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/metric/DefaultMetricFinder.java b/server/sonar-server/src/main/java/org/sonar/server/metric/DefaultMetricFinder.java new file mode 100644 index 00000000000..91433ef356f --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/metric/DefaultMetricFinder.java @@ -0,0 +1,126 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.metric; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import javax.annotation.Nonnull; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.MetricFinder; +import org.sonar.core.metric.db.MetricDto; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; +import org.sonar.server.db.DbClient; + +import static com.google.common.collect.FluentIterable.from; + +public class DefaultMetricFinder implements MetricFinder { + + private final DbClient dbClient; + + public DefaultMetricFinder(DbClient dbClient) { + this.dbClient = dbClient; + } + + @Override + public Metric findById(int id) { + DbSession session = dbClient.openSession(false); + try { + MetricDto dto = dbClient.metricDao().selectNullableById(session, id); + if (dto != null && dto.isEnabled()) { + return ToMetric.INSTANCE.apply(dto); + } + return null; + } finally { + MyBatis.closeQuietly(session); + } + } + + @Override + public Metric findByKey(String key) { + DbSession session = dbClient.openSession(false); + try { + MetricDto dto = dbClient.metricDao().selectNullableByKey(session, key); + if (dto != null && dto.isEnabled()) { + return ToMetric.INSTANCE.apply(dto); + } + return null; + } finally { + MyBatis.closeQuietly(session); + } + } + + @Override + public Collection<Metric> findAll(List<String> metricKeys) { + DbSession session = dbClient.openSession(false); + try { + List<MetricDto> dtos = dbClient.metricDao().selectNullableByKeys(session, metricKeys); + return from(dtos).filter(IsEnabled.INSTANCE).transform(ToMetric.INSTANCE).toList(); + } finally { + MyBatis.closeQuietly(session); + } + } + + @Override + public Collection<Metric> findAll() { + DbSession session = dbClient.openSession(false); + try { + List<MetricDto> dtos = dbClient.metricDao().selectEnabled(session); + return from(dtos).transform(ToMetric.INSTANCE).toList(); + } finally { + MyBatis.closeQuietly(session); + } + } + + private enum IsEnabled implements Predicate<MetricDto> { + INSTANCE; + @Override + public boolean apply(@Nonnull MetricDto dto) { + return dto.isEnabled(); + } + } + + private enum ToMetric implements Function<MetricDto, Metric> { + INSTANCE; + + @Override + public Metric apply(@Nonnull MetricDto dto) { + Metric<Serializable> metric = new Metric<>(); + metric.setId(dto.getId()); + metric.setKey(dto.getKey()); + metric.setDescription(dto.getDescription()); + metric.setName(dto.getShortName()); + metric.setBestValue(dto.getBestValue()); + metric.setDomain(dto.getDomain()); + metric.setEnabled(dto.isEnabled()); + metric.setDirection(dto.getDirection()); + metric.setHidden(dto.isHidden()); + metric.setQualitative(dto.isQualitative()); + metric.setType(Metric.ValueType.valueOf(dto.getValueType())); + metric.setOptimizedBestValue(dto.isOptimizedBestValue()); + metric.setUserManaged(dto.isUserManaged()); + metric.setWorstValue(dto.getWorstValue()); + return metric; + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/metric/persistence/MetricDao.java b/server/sonar-server/src/main/java/org/sonar/server/metric/persistence/MetricDao.java index 8765806f735..0be58572229 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/metric/persistence/MetricDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/metric/persistence/MetricDao.java @@ -112,16 +112,20 @@ public class MetricDao implements DaoComponent { return session.getMapper(MetricMapper.class); } - public void disable(final DbSession session, List<Integer> ids) { + public void disableByIds(final DbSession session, List<Integer> ids) { DaoUtils.executeLargeInputsWithoutOutput(ids, new Function<List<Integer>, Void>() { @Override public Void apply(@Nonnull List<Integer> input) { - mapper(session).disable(input); + mapper(session).disableByIds(input); return null; } }); } + public void disableByKey(final DbSession session, String key) { + mapper(session).disableByKey(key); + } + public void update(DbSession session, MetricDto metric) { mapper(session).update(metric); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/metric/ws/DeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/metric/ws/DeleteAction.java index d388560ba89..5ef5649bf4e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/metric/ws/DeleteAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/metric/ws/DeleteAction.java @@ -74,7 +74,7 @@ public class DeleteAction implements MetricsWsAction { DbSession dbSession = dbClient.openSession(false); try { List<Integer> ids = loadIds(dbSession, request); - dbClient.metricDao().disable(dbSession, ids); + dbClient.metricDao().disableByIds(dbSession, ids); dbClient.customMeasureDao().deleteByMetricIds(dbSession, ids); dbSession.commit(); } finally { diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index 42ef539aa6c..85f0d0495e9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -37,7 +37,6 @@ import org.sonar.core.issue.IssueFilterSerializer; import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.workflow.FunctionExecutor; import org.sonar.core.issue.workflow.IssueWorkflow; -import org.sonar.core.metric.DefaultMetricFinder; import org.sonar.core.permission.PermissionFacade; import org.sonar.core.qualitygate.db.ProjectQgateAssociationDao; import org.sonar.core.qualitygate.db.QualityGateConditionDao; @@ -46,7 +45,6 @@ import org.sonar.core.resource.DefaultResourceTypes; import org.sonar.core.timemachine.Periods; import org.sonar.core.user.DefaultUserFinder; import org.sonar.core.user.DeprecatedUserFinder; -import org.sonar.jpa.dao.MeasuresDao; import org.sonar.server.activity.ActivityService; import org.sonar.server.activity.RubyQProfileActivityService; import org.sonar.server.activity.index.ActivityIndex; @@ -170,6 +168,7 @@ import org.sonar.server.measure.template.ProjectFilter; import org.sonar.server.measure.ws.ManualMeasuresWs; import org.sonar.server.measure.ws.TimeMachineWs; import org.sonar.server.metric.CoreCustomMetrics; +import org.sonar.server.metric.DefaultMetricFinder; import org.sonar.server.metric.ws.MetricsWsModule; import org.sonar.server.notification.DefaultNotificationManager; import org.sonar.server.notification.NotificationCenter; @@ -486,8 +485,6 @@ public class PlatformLevel4 extends PlatformLevel { ActivityMapping.class, // measure - MeasuresDao.class, - MeasureFilterFactory.class, MeasureFilterExecutor.class, MeasureFilterEngine.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/startup/RegisterMetrics.java b/server/sonar-server/src/main/java/org/sonar/server/startup/RegisterMetrics.java index 23636e51133..1000c1078e6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/startup/RegisterMetrics.java +++ b/server/sonar-server/src/main/java/org/sonar/server/startup/RegisterMetrics.java @@ -20,99 +20,142 @@ package org.sonar.server.startup; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Predicate; -import com.google.common.collect.Iterables; +import com.google.common.base.Function; import com.google.common.collect.Maps; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.annotation.Nonnull; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; import org.sonar.api.measures.Metrics; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.api.utils.log.Profiler; -import org.sonar.core.qualitygate.db.QualityGateConditionDao; -import org.sonar.jpa.dao.MeasuresDao; - -import java.util.List; -import java.util.Map; +import org.sonar.core.metric.db.MetricDto; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; +import org.sonar.server.db.DbClient; +import static com.google.common.collect.FluentIterable.from; +import static com.google.common.collect.Iterables.concat; import static com.google.common.collect.Lists.newArrayList; public class RegisterMetrics { private static final Logger LOG = Loggers.get(RegisterMetrics.class); - private final MeasuresDao measuresDao; + private final DbClient dbClient; private final Metrics[] metricsRepositories; - private final QualityGateConditionDao conditionDao; - public RegisterMetrics(MeasuresDao measuresDao, QualityGateConditionDao conditionDao, Metrics[] metricsRepositories) { - this.measuresDao = measuresDao; + public RegisterMetrics(DbClient dbClient, Metrics[] metricsRepositories) { + this.dbClient = dbClient; this.metricsRepositories = metricsRepositories; - this.conditionDao = conditionDao; } /** * Used when no plugin is defining Metrics */ - public RegisterMetrics(MeasuresDao measuresDao, QualityGateConditionDao conditionDao) { - this(measuresDao, conditionDao, new Metrics[]{}); + public RegisterMetrics(DbClient dbClient) { + this(dbClient, new Metrics[] {}); } public void start() { - Profiler profiler = Profiler.create(LOG).startInfo("Register metrics"); - measuresDao.disableAutomaticMetrics(); + register(concat(CoreMetrics.getMetrics(), getPluginMetrics())); + } - List<Metric> metricsToRegister = newArrayList(); - metricsToRegister.addAll(CoreMetrics.getMetrics()); - metricsToRegister.addAll(getMetricsRepositories()); - register(metricsToRegister); - cleanAlerts(); + void register(Iterable<Metric> metrics) { + Profiler profiler = Profiler.create(LOG).startInfo("Register metrics"); + DbSession session = dbClient.openSession(false); + try { + save(session, metrics); + sanitizeQualityGates(session); + session.commit(); + } finally { + MyBatis.closeQuietly(session); + } profiler.stopDebug(); } + private void sanitizeQualityGates(DbSession session) { + dbClient.gateConditionDao().deleteConditionsWithInvalidMetrics(session); + } + + private void save(DbSession session, Iterable<Metric> metrics) { + Map<String, MetricDto> basesByKey = new HashMap<>(); + for (MetricDto base : from(dbClient.metricDao().selectEnabled(session)).toList()) { + basesByKey.put(base.getKey(), base); + } + + for (Metric metric : metrics) { + MetricDto dto = MetricToDto.INSTANCE.apply(metric); + MetricDto base = basesByKey.get(metric.getKey()); + if (base == null) { + // new metric, never installed + dbClient.metricDao().insert(session, dto); + } else if (!base.isUserManaged()) { + // existing metric, update changes. Existing custom metrics are kept without applying changes. + dto.setId(base.getId()); + dbClient.metricDao().update(session, dto); + } + basesByKey.remove(metric.getKey()); + } + + for (MetricDto nonUpdatedBase : basesByKey.values()) { + if (!nonUpdatedBase.isUserManaged()) { + LOG.info("Disable metric {} [{}]", nonUpdatedBase.getShortName(), nonUpdatedBase.getKey()); + dbClient.metricDao().disableByKey(session, nonUpdatedBase.getKey()); + } + } + } + @VisibleForTesting - List<Metric> getMetricsRepositories() { + List<Metric> getPluginMetrics() { List<Metric> metricsToRegister = newArrayList(); Map<String, Metrics> metricsByRepository = Maps.newHashMap(); - for (Metrics metrics : metricsRepositories) { checkMetrics(metricsByRepository, metrics); - metricsToRegister.addAll(removeExistingUserManagedMetrics(metrics.getMetrics())); + metricsToRegister.addAll(metrics.getMetrics()); } return metricsToRegister; } - private List<Metric> removeExistingUserManagedMetrics(List<Metric> metrics) { - return newArrayList(Iterables.filter(metrics, new Predicate<Metric>() { - @Override - public boolean apply(Metric metric) { - // It should be better to use the template mechanism (as it's done in #RegisterDashboards to register provided user manager metrics - return !metric.getUserManaged() || measuresDao.getMetric(metric.getKey()) == null; - } - })); - } - private void checkMetrics(Map<String, Metrics> metricsByRepository, Metrics metrics) { for (Metric metric : metrics.getMetrics()) { String metricKey = metric.getKey(); if (CoreMetrics.getMetrics().contains(metric)) { - throw new IllegalStateException("The following metric is already defined in sonar: " + metricKey); + throw new IllegalStateException(String.format("Metric [%s] is already defined by SonarQube", metricKey)); } Metrics anotherRepository = metricsByRepository.get(metricKey); if (anotherRepository != null) { - throw new IllegalStateException("The metric '" + metricKey + "' is already defined in the extension: " + anotherRepository); + throw new IllegalStateException(String.format("Metric [%s] is already defined by the repository [%s]", metricKey, anotherRepository)); } metricsByRepository.put(metricKey, metrics); } } - protected void cleanAlerts() { - LOG.info("Cleaning quality gate conditions"); - conditionDao.deleteConditionsWithInvalidMetrics(); - } - - protected void register(List<Metric> metrics) { - measuresDao.registerMetrics(metrics); + private enum MetricToDto implements Function<Metric, MetricDto> { + INSTANCE; + @Override + @Nonnull + public MetricDto apply(@Nonnull Metric metric) { + MetricDto dto = new MetricDto(); + dto.setId(metric.getId()); + dto.setKey(metric.getKey()); + dto.setDescription(metric.getDescription()); + dto.setShortName(metric.getName()); + dto.setBestValue(metric.getBestValue()); + dto.setDomain(metric.getDomain()); + dto.setEnabled(metric.getEnabled()); + dto.setDirection(metric.getDirection()); + dto.setHidden(metric.isHidden()); + dto.setQualitative(metric.getQualitative()); + dto.setValueType(metric.getType().name()); + dto.setOptimizedBestValue(metric.isOptimizedBestValue()); + dto.setUserManaged(metric.getUserManaged()); + dto.setWorstValue(metric.getWorstValue()); + return dto; + } } } diff --git a/sonar-core/src/test/java/org/sonar/core/metric/DefaultMetricFinderTest.java b/server/sonar-server/src/test/java/org/sonar/server/metric/DefaultMetricFinderTest.java index 34a00af08de..3d257d40b1a 100644 --- a/sonar-core/src/test/java/org/sonar/core/metric/DefaultMetricFinderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/metric/DefaultMetricFinderTest.java @@ -17,25 +17,34 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.core.metric; +package org.sonar.server.metric; import java.util.Arrays; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; -import org.sonar.jpa.test.AbstractDbUnitTestCase; +import org.junit.experimental.categories.Category; +import org.sonar.core.persistence.DbTester; +import org.sonar.server.db.DbClient; +import org.sonar.server.metric.persistence.MetricDao; +import org.sonar.test.DbTests; import static org.hamcrest.core.Is.is; import static org.hamcrest.core.IsNull.nullValue; import static org.junit.Assert.assertThat; -public class DefaultMetricFinderTest extends AbstractDbUnitTestCase { +@Category(DbTests.class) +public class DefaultMetricFinderTest { - private DefaultMetricFinder finder; + @ClassRule + public static DbTester dbTester = new DbTester(); + + DefaultMetricFinder finder; @Before public void setUp() { - setupData("shared"); - finder = new DefaultMetricFinder(getSessionFactory()); + dbTester.prepareDbUnit(DefaultMetricFinderTest.class, "shared.xml"); + finder = new DefaultMetricFinder(new DbClient(dbTester.database(), dbTester.myBatis(), new MetricDao())); } @Test @@ -45,7 +54,7 @@ public class DefaultMetricFinderTest extends AbstractDbUnitTestCase { @Test public void shouldFindByKeys() { - assertThat(finder.findAll(Arrays.<String> asList("ncloc", "foo", "coverage")).size(), is(2)); + assertThat(finder.findAll(Arrays.asList("ncloc", "foo", "coverage")).size(), is(2)); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java b/server/sonar-server/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java index af536fab964..c37600379b9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/startup/RegisterMetricsTest.java @@ -19,120 +19,127 @@ */ package org.sonar.server.startup; -import com.google.common.collect.Lists; +import java.util.Collections; +import java.util.List; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.experimental.categories.Category; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; import org.sonar.api.measures.Metrics; +import org.sonar.core.persistence.DbTester; import org.sonar.core.qualitygate.db.QualityGateConditionDao; -import org.sonar.jpa.dao.MeasuresDao; -import org.sonar.jpa.test.AbstractDbUnitTestCase; - -import java.util.Arrays; -import java.util.List; +import org.sonar.server.db.DbClient; +import org.sonar.server.metric.persistence.MetricDao; +import org.sonar.test.DbTests; +import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -public class RegisterMetricsTest extends AbstractDbUnitTestCase { +@Category(DbTests.class) +public class RegisterMetricsTest { + + @ClassRule + public static DbTester dbTester = new DbTester(); + /** + * Insert new metrics, including custom metrics + */ @Test - public void shouldSaveIfNew() { - setupData("shouldSaveIfNew"); + public void insert_new_metrics() { + dbTester.prepareDbUnit(getClass(), "insert_new_metrics.xml"); - Metric metric1 = new Metric.Builder("new1", "short1", Metric.ValueType.FLOAT) + Metric m1 = new Metric.Builder("m1", "One", Metric.ValueType.FLOAT) .setDescription("desc1") .setDirection(1) .setQualitative(true) .setDomain("domain1") .setUserManaged(false) .create(); - Metric metric2 = new Metric.Builder("new2", "short2", Metric.ValueType.FLOAT) - .setDescription("desc2") - .setDirection(1) - .setQualitative(true) - .setDomain("domain2") - .setUserManaged(false) + Metric custom = new Metric.Builder("custom", "Custom", Metric.ValueType.FLOAT) + .setDescription("This is a custom metric") + .setUserManaged(true) .create(); - RegisterMetrics synchronizer = new RegisterMetrics(new MeasuresDao(getSession()), mock(QualityGateConditionDao.class), new Metrics[0]); - synchronizer.register(Arrays.asList(metric1, metric2)); - checkTables("shouldSaveIfNew", "metrics"); + RegisterMetrics register = new RegisterMetrics(dbClient()); + register.register(asList(m1, custom)); + dbTester.assertDbUnit(getClass(), "insert_new_metrics-result.xml", "metrics"); } + /** + * Update existing metrics, except if custom metric + */ @Test - public void shouldUpdateIfAlreadyExists() { - setupData("shouldUpdateIfAlreadyExists"); + public void update_non_custom_metrics() { + dbTester.prepareDbUnit(getClass(), "update_non_custom_metrics.xml"); - RegisterMetrics synchronizer = new RegisterMetrics(new MeasuresDao(getSession()), mock(QualityGateConditionDao.class), new Metrics[0]); - synchronizer.register(Lists.<Metric>newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT) + RegisterMetrics register = new RegisterMetrics(dbClient()); + Metric m1 = new Metric.Builder("m1", "New name", Metric.ValueType.FLOAT) .setDescription("new description") .setDirection(-1) .setQualitative(true) .setDomain("new domain") .setUserManaged(false) - .create())); + .setHidden(true) + .create(); + Metric custom = new Metric.Builder("custom", "New custom", Metric.ValueType.FLOAT) + .setDescription("New description of custom metric") + .setUserManaged(true) + .create(); + register.register(asList(m1, custom)); - checkTables("shouldUpdateIfAlreadyExists", "metrics"); + dbTester.assertDbUnit(getClass(), "update_non_custom_metrics-result.xml", "metrics"); } @Test - public void shouldAddUserManagesMetric() { - Metrics metrics = mock(Metrics.class); - when(metrics.getMetrics()).thenReturn(Lists.<Metric>newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT) - .setDescription("new description") - .setDirection(-1) - .setQualitative(true) - .setDomain("new domain") - .setUserManaged(true) - .create())); + public void disable_undefined_metrics() { + dbTester.prepareDbUnit(getClass(), "disable_undefined_metrics.xml"); - MeasuresDao measuresDao = new MeasuresDao(getSession()); - RegisterMetrics loader = new RegisterMetrics(measuresDao, mock(QualityGateConditionDao.class), new Metrics[] {metrics}); - List<Metric> result = loader.getMetricsRepositories(); + RegisterMetrics register = new RegisterMetrics(dbClient()); + register.register(Collections.<Metric>emptyList()); - assertThat(result).hasSize(1); + dbTester.assertDbUnit(getClass(), "disable_undefined_metrics-result.xml", "metrics"); } @Test - public void shouldNotUpdateUserManagesMetricIfAlreadyExists() { - setupData("shouldNotUpdateUserManagesMetricIfAlreadyExists"); + public void insert_core_metrics() { + dbTester.truncateTables(); - Metrics metrics = mock(Metrics.class); - when(metrics.getMetrics()).thenReturn(Lists.<Metric>newArrayList(new Metric.Builder("key", "new short name", Metric.ValueType.FLOAT) - .setDescription("new description") - .setDirection(-1) - .setQualitative(true) - .setDomain("new domain") - .setUserManaged(true) - .create())); + RegisterMetrics register = new RegisterMetrics(dbClient()); + register.start(); - MeasuresDao measuresDao = new MeasuresDao(getSession()); - RegisterMetrics loader = new RegisterMetrics(measuresDao, mock(QualityGateConditionDao.class), new Metrics[] {metrics}); - List<Metric> result = loader.getMetricsRepositories(); + assertThat(dbTester.countRowsOfTable("metrics")).isEqualTo(CoreMetrics.getMetrics().size()); + } + + @Test(expected = IllegalStateException.class) + public void fail_if_duplicated_plugin_metrics() throws Exception { + Metrics plugin1 = new TestMetrics(new Metric.Builder("m1", "In first plugin", Metric.ValueType.FLOAT).create()); + Metrics plugin2 = new TestMetrics(new Metric.Builder("m1", "In second plugin", Metric.ValueType.FLOAT).create()); - assertThat(result).isEmpty(); + new RegisterMetrics(dbClient(), new Metrics[]{plugin1, plugin2}).start(); } - @Test - public void shouldEnableOnlyLoadedMetrics() { - setupData("shouldEnableOnlyLoadedMetrics"); + @Test(expected = IllegalStateException.class) + public void fail_if_plugin_duplicates_core_metric() throws Exception { + Metrics plugin = new TestMetrics(new Metric.Builder("ncloc", "In plugin", Metric.ValueType.FLOAT).create()); - MeasuresDao measuresDao = new MeasuresDao(getSession()); - RegisterMetrics loader = new RegisterMetrics(measuresDao, mock(QualityGateConditionDao.class), new Metrics[0]); - loader.start(); + new RegisterMetrics(dbClient(), new Metrics[]{plugin}).start(); + } - assertThat(measuresDao.getMetric("deprecated").getEnabled()).isFalse(); - assertThat(measuresDao.getMetric(CoreMetrics.COMPLEXITY_KEY).getEnabled()).isTrue(); + private DbClient dbClient() { + return new DbClient(dbTester.database(), dbTester.myBatis(), new MetricDao(), new QualityGateConditionDao(dbTester.myBatis())); } - @Test - public void clean_quality_gate_conditions() { - QualityGateConditionDao conditionDao = mock(QualityGateConditionDao.class); - RegisterMetrics loader = new RegisterMetrics(new MeasuresDao(getSession()), conditionDao, new Metrics[0]); - loader.cleanAlerts(); - verify(conditionDao).deleteConditionsWithInvalidMetrics(); + private class TestMetrics implements Metrics { + private final List<Metric> metrics; + + public TestMetrics(Metric... metrics) { + this.metrics = asList(metrics); + } + + @Override + public List<Metric> getMetrics() { + return metrics; + } } } diff --git a/sonar-core/src/test/resources/org/sonar/core/metric/DefaultMetricFinderTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/metric/DefaultMetricFinderTest/shared.xml index dd645d66ec1..dd645d66ec1 100644 --- a/sonar-core/src/test/resources/org/sonar/core/metric/DefaultMetricFinderTest/shared.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/metric/DefaultMetricFinderTest/shared.xml diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/disable_undefined_metrics-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/disable_undefined_metrics-result.xml new file mode 100644 index 00000000000..dbedde99411 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/disable_undefined_metrics-result.xml @@ -0,0 +1,8 @@ +<dataset> + + <!-- disabled --> + <metrics delete_historical_data="[false]" id="1" name="m1" val_type="FLOAT" description="desc1" domain="domain1" + short_name="One" qualitative="[true]" user_managed="[false]" enabled="[false]" worst_value="[null]" + optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]"/> + +</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/disable_undefined_metrics.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/disable_undefined_metrics.xml new file mode 100644 index 00000000000..b48ad61cd33 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/disable_undefined_metrics.xml @@ -0,0 +1,9 @@ +<dataset> + + <metrics delete_historical_data="[false]" id="1" name="m1" val_type="FLOAT" description="desc1" domain="domain1" + short_name="One" qualitative="[true]" user_managed="[false]" + enabled="[true]" + worst_value="[null]" + optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]"/> + +</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/insert_new_metrics-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/insert_new_metrics-result.xml new file mode 100644 index 00000000000..1bb5088d8e0 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/insert_new_metrics-result.xml @@ -0,0 +1,11 @@ +<dataset> + + <metrics delete_historical_data="[false]" id="1" name="m1" val_type="FLOAT" description="desc1" domain="domain1" + short_name="One" qualitative="[true]" user_managed="[false]" enabled="[true]" worst_value="[null]" + optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]"/> + <metrics delete_historical_data="[false]" id="2" name="custom" val_type="FLOAT" description="This is a custom metric" + domain="[null]" + short_name="Custom" qualitative="[false]" user_managed="[true]" enabled="[true]" worst_value="[null]" + optimized_best_value="[false]" best_value="[null]" direction="0" hidden="[false]"/> + +</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/insert_new_metrics.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/insert_new_metrics.xml new file mode 100644 index 00000000000..a1c54e4625a --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/insert_new_metrics.xml @@ -0,0 +1,4 @@ +<dataset> + + +</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldAddUserManagesMetric-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldAddUserManagesMetric-result.xml deleted file mode 100644 index e00703108a3..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldAddUserManagesMetric-result.xml +++ /dev/null @@ -1,6 +0,0 @@ -<dataset> - - <metrics delete_historical_data="false" id="1" name="key" val_type="FLOAT" description="new description" domain="new domain" - short_name="new short name" qualitative="true" user_managed="true" enabled="true" worst_value="[null]" optimized_best_value="false" best_value="[null]" direction="-1" hidden="false"/> - -</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldAddUserManagesMetric.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldAddUserManagesMetric.xml deleted file mode 100644 index f1e73ac59ed..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldAddUserManagesMetric.xml +++ /dev/null @@ -1,5 +0,0 @@ -<dataset> - - <metrics/> - -</dataset>
\ No newline at end of file diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldEnableOnlyLoadedMetrics.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldEnableOnlyLoadedMetrics.xml deleted file mode 100644 index 93aa067888f..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldEnableOnlyLoadedMetrics.xml +++ /dev/null @@ -1,6 +0,0 @@ -<dataset> - - <metrics delete_historical_data="false" id="1" name="deprecated" val_type="INT" description="description" domain="domain" - short_name="short name" qualitative="false" user_managed="false" enabled="true" worst_value="[null]" optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> - -</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldNotUpdateUserManagesMetricIfAlreadyExists-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldNotUpdateUserManagesMetricIfAlreadyExists-result.xml deleted file mode 100644 index 968b9e9f3d8..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldNotUpdateUserManagesMetricIfAlreadyExists-result.xml +++ /dev/null @@ -1,6 +0,0 @@ -<dataset> - - <metrics delete_historical_data="false" id="1" name="key" val_type="INT" description="old description" domain="old domain" - short_name="old short name" qualitative="false" user_managed="true" enabled="true" worst_value="[null]" optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> - -</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldNotUpdateUserManagesMetricIfAlreadyExists.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldNotUpdateUserManagesMetricIfAlreadyExists.xml deleted file mode 100644 index ed24c0d990a..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldNotUpdateUserManagesMetricIfAlreadyExists.xml +++ /dev/null @@ -1,7 +0,0 @@ -<dataset> - - <metrics delete_historical_data="false" id="1" name="key" val_type="INT" description="old description" domain="old domain" - short_name="old short name" qualitative="false" user_managed="true" enabled="true" worst_value="[null]" optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> - - -</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldSaveIfNew-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldSaveIfNew-result.xml deleted file mode 100644 index 182a4a8e3bb..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldSaveIfNew-result.xml +++ /dev/null @@ -1,12 +0,0 @@ -<dataset> - - <metrics delete_historical_data="false" id="1" name="key1" val_type="INT" description="description" domain="domain" - short_name="short name" qualitative="false" user_managed="false" enabled="true" worst_value="[null]" optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> - - <!--New metrics --> - <metrics delete_historical_data="false" id="2" name="new1" val_type="FLOAT" description="desc1" domain="domain1" - short_name="short1" qualitative="true" user_managed="false" enabled="true" worst_value="[null]" optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> - <metrics delete_historical_data="false" id="3" name="new2" val_type="FLOAT" description="desc2" domain="domain2" - short_name="short2" qualitative="true" user_managed="false" enabled="true" worst_value="[null]" optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> - -</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldSaveIfNew.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldSaveIfNew.xml deleted file mode 100644 index 3f7c90205e1..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldSaveIfNew.xml +++ /dev/null @@ -1,6 +0,0 @@ -<dataset> - - <metrics delete_historical_data="false" id="1" name="key1" val_type="INT" description="description" domain="domain" - short_name="short name" qualitative="false" user_managed="false" enabled="true" worst_value="[null]" optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> - -</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldUpdateIfAlreadyExists-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldUpdateIfAlreadyExists-result.xml deleted file mode 100644 index ed9a86d0f2a..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldUpdateIfAlreadyExists-result.xml +++ /dev/null @@ -1,6 +0,0 @@ -<dataset> - - <metrics delete_historical_data="false" id="1" name="key" val_type="FLOAT" description="new description" domain="new domain" - short_name="new short name" qualitative="true" user_managed="false" enabled="true" worst_value="[null]" optimized_best_value="false" best_value="[null]" direction="-1" hidden="false"/> - -</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldUpdateIfAlreadyExists.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldUpdateIfAlreadyExists.xml deleted file mode 100644 index fb9242edb48..00000000000 --- a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/shouldUpdateIfAlreadyExists.xml +++ /dev/null @@ -1,7 +0,0 @@ -<dataset> - - <metrics delete_historical_data="false" id="1" name="key" val_type="INT" description="old description" domain="old domain" - short_name="old short name" qualitative="false" user_managed="false" enabled="true" worst_value="[null]" optimized_best_value="false" best_value="[null]" direction="1" hidden="false"/> - - -</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/update_non_custom_metrics-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/update_non_custom_metrics-result.xml new file mode 100644 index 00000000000..886e1d2d8f4 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/update_non_custom_metrics-result.xml @@ -0,0 +1,15 @@ +<dataset> + + <!-- changed --> + <metrics delete_historical_data="[false]" id="1" name="m1" val_type="FLOAT" description="new description" + domain="new domain" + short_name="New name" qualitative="[true]" user_managed="[false]" enabled="[true]" worst_value="[null]" + optimized_best_value="[false]" best_value="[null]" direction="-1" hidden="[true]"/> + + <!-- custom metric is unchanged --> + <metrics delete_historical_data="[false]" id="2" name="custom" val_type="FLOAT" description="This is a custom metric" + domain="[null]" + short_name="Custom" qualitative="[false]" user_managed="[true]" enabled="[true]" worst_value="[null]" + optimized_best_value="[false]" best_value="[null]" direction="0" hidden="[false]"/> + +</dataset> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/update_non_custom_metrics.xml b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/update_non_custom_metrics.xml new file mode 100644 index 00000000000..483a9cb43c6 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/startup/RegisterMetricsTest/update_non_custom_metrics.xml @@ -0,0 +1,12 @@ +<dataset> + + <metrics delete_historical_data="[false]" id="1" name="m1" val_type="INT" description="old description" + domain="old domain" + short_name="old short name" qualitative="[false]" user_managed="[false]" enabled="[true]" worst_value="[null]" + optimized_best_value="[false]" best_value="[null]" direction="1" hidden="[false]"/> + + <metrics delete_historical_data="[false]" id="2" name="custom" val_type="FLOAT" description="This is a custom metric" + domain="[null]" + short_name="Custom" qualitative="[false]" user_managed="[true]" enabled="[true]" worst_value="[null]" + optimized_best_value="[false]" best_value="[null]" direction="0" hidden="[false]"/> +</dataset> diff --git a/sonar-core/src/main/java/org/sonar/core/metric/DefaultMetricFinder.java b/sonar-core/src/main/java/org/sonar/core/metric/DefaultMetricFinder.java deleted file mode 100644 index 087a6be91b8..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/metric/DefaultMetricFinder.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.core.metric; - -import com.google.common.collect.Lists; -import org.sonar.api.measures.Metric; -import org.sonar.api.measures.MetricFinder; -import org.sonar.jpa.session.DatabaseSessionFactory; - -import java.util.Collection; -import java.util.List; - -public class DefaultMetricFinder implements MetricFinder { - - private static final String ENABLED = "enabled"; - private DatabaseSessionFactory sessionFactory; - - public DefaultMetricFinder(DatabaseSessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - - @Override - public Metric findById(int id) { - return sessionFactory.getSession().getSingleResult(Metric.class, "id", id, ENABLED, true); - } - - @Override - public Metric findByKey(String key) { - return sessionFactory.getSession().getSingleResult(Metric.class, "key", key, ENABLED, true); - } - - @Override - public Collection<Metric> findAll(List<String> metricKeys) { - List<Metric> result = Lists.newLinkedList(); - for (String metricKey : metricKeys) { - Metric metric = findByKey(metricKey); - if (metric != null) { - result.add(metric); - } - } - return result; - } - - @Override - public Collection<Metric> findAll() { - return doFindAll(); - } - - protected Collection<Metric> doFindAll() { - return sessionFactory.getSession().getResults(Metric.class, ENABLED, true); - } - -} diff --git a/sonar-core/src/main/java/org/sonar/core/metric/db/MetricMapper.java b/sonar-core/src/main/java/org/sonar/core/metric/db/MetricMapper.java index dd216603d05..280fb82f4e0 100644 --- a/sonar-core/src/main/java/org/sonar/core/metric/db/MetricMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/metric/db/MetricMapper.java @@ -40,7 +40,9 @@ public interface MetricMapper { List<MetricDto> selectByKeys(@Param("keys") List<String> keys); - void disable(@Param("ids") List<Integer> ids); + void disableByIds(@Param("ids") List<Integer> ids); + + void disableByKey(@Param("key") String key); int countEnabled(@Param("isCustom") @Nullable Boolean isCustom); diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java b/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java index 03372a70717..17764552b20 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java @@ -39,6 +39,7 @@ import org.sonar.core.permission.PermissionDao; import org.sonar.core.permission.PermissionTemplateDao; import org.sonar.core.properties.PropertiesDao; import org.sonar.core.purge.PurgeDao; +import org.sonar.core.qualitygate.db.QualityGateConditionDao; import org.sonar.core.qualityprofile.db.ActiveRuleDao; import org.sonar.core.qualityprofile.db.QualityProfileDao; import org.sonar.core.resource.ResourceDao; @@ -84,6 +85,7 @@ public final class DaoUtils { PermissionDao.class, PermissionTemplateDao.class, PropertiesDao.class, + QualityGateConditionDao.class, QualityProfileDao.class, PurgeDao.class, CharacteristicDao.class, diff --git a/sonar-core/src/main/java/org/sonar/core/qualitygate/db/QualityGateConditionDao.java b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/QualityGateConditionDao.java index a634f15bf61..5c1eec7664f 100644 --- a/sonar-core/src/main/java/org/sonar/core/qualitygate/db/QualityGateConditionDao.java +++ b/sonar-core/src/main/java/org/sonar/core/qualitygate/db/QualityGateConditionDao.java @@ -20,6 +20,7 @@ package org.sonar.core.qualitygate.db; import org.apache.ibatis.session.SqlSession; +import org.sonar.core.persistence.DaoComponent; import org.sonar.core.persistence.MyBatis; import java.util.Collection; @@ -28,7 +29,7 @@ import java.util.Date; /** * @since 4.3 */ -public class QualityGateConditionDao { +public class QualityGateConditionDao implements DaoComponent { private final MyBatis myBatis; diff --git a/sonar-core/src/main/java/org/sonar/jpa/dao/MeasuresDao.java b/sonar-core/src/main/java/org/sonar/jpa/dao/MeasuresDao.java deleted file mode 100644 index 372674b94c4..00000000000 --- a/sonar-core/src/main/java/org/sonar/jpa/dao/MeasuresDao.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.jpa.dao; - -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.Predicate; -import org.sonar.api.database.DatabaseSession; -import org.sonar.api.measures.Metric; - -public class MeasuresDao { - - private final DatabaseSession session; - private final Map<String, Metric> metricsByName = new HashMap<>(); - - public MeasuresDao(DatabaseSession session) { - this.session = session; - } - - public Metric getMetric(String metricName) { - return getMetricsByName().get(metricName); - } - - public Collection<Metric> getMetrics() { - return getMetricsByName().values(); - } - - public Collection<Metric> getEnabledMetrics() { - return CollectionUtils.select(getMetricsByName().values(), new Predicate() { - @Override - public boolean evaluate(Object o) { - return ((Metric) o).getEnabled(); - } - }); - } - - public void disableAutomaticMetrics() { - session.createQuery("update " + Metric.class.getSimpleName() + " m set m.enabled=false where m.userManaged=false").executeUpdate(); - session.commit(); - metricsByName.clear(); - } - - public void registerMetrics(Collection<Metric> metrics) { - if (metrics != null) { - for (Metric metric : metrics) { - metric.setEnabled(Boolean.TRUE); - persistMetricWithoutClear(metric); - } - session.commit(); - } - metricsByName.clear(); - } - - private void persistMetricWithoutClear(Metric metric) { - Metric dbMetric = getMetric(metric.getKey()); - if (dbMetric != null) { - dbMetric.merge(metric); - session.getEntityManager().merge(dbMetric); - - } else { - session.getEntityManager().persist(new Metric().merge(metric)); - } - } - - private Map<String, Metric> getMetricsByName() { - if (metricsByName.isEmpty()) { - List<Metric> metrics = session.getResults(Metric.class); - for (Metric metric : metrics) { - metricsByName.put(metric.getKey(), metric); - } - } - return metricsByName; - } - -} diff --git a/sonar-core/src/main/resources/org/sonar/core/metric/db/MetricMapper.xml b/sonar-core/src/main/resources/org/sonar/core/metric/db/MetricMapper.xml index 9278b7252a5..a91e4c49259 100644 --- a/sonar-core/src/main/resources/org/sonar/core/metric/db/MetricMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/metric/db/MetricMapper.xml @@ -47,6 +47,7 @@ </where> ORDER BY UPPER(m.short_name), m.short_name </select> + <select id="countEnabled" resultType="Integer"> SELECT COUNT(*) FROM metrics m @@ -85,7 +86,10 @@ val_type=#{valueType, jdbcType=VARCHAR}, enabled=#{enabled, jdbcType=BOOLEAN}, domain=#{domain, jdbcType=VARCHAR}, - description=#{description, jdbcType=VARCHAR} + description=#{description, jdbcType=VARCHAR}, + direction=#{direction, jdbcType=INTEGER}, + hidden=#{hidden, jdbcType=BOOLEAN}, + qualitative=#{qualitative, jdbcType=BOOLEAN} where id=#{id} </update> @@ -95,7 +99,7 @@ where m.domain is not null and m.enabled=${_true} </select> - <update id="disable"> + <update id="disableByIds"> update metrics set enabled=${_false} <where> @@ -107,6 +111,12 @@ </where> </update> + <update id="disableByKey" parameterType="string"> + update metrics + set enabled=${_false} + where name=#{key} + </update> + <select id="selectByKeys" resultType="org.sonar.core.metric.db.MetricDto"> SELECT <include refid="metricColumns"/> diff --git a/sonar-core/src/test/java/org/sonar/jpa/dao/MeasuresDaoTest.java b/sonar-core/src/test/java/org/sonar/jpa/dao/MeasuresDaoTest.java deleted file mode 100644 index 3c9d299cd3b..00000000000 --- a/sonar-core/src/test/java/org/sonar/jpa/dao/MeasuresDaoTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.jpa.dao; - -import java.util.Arrays; -import java.util.Collection; -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.database.model.ResourceModel; -import org.sonar.api.measures.Metric; -import org.sonar.jpa.test.AbstractDbUnitTestCase; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; - -public class MeasuresDaoTest extends AbstractDbUnitTestCase { - - private MeasuresDao service; - private ResourceModel project; - - @Before - public void before() { - service = new MeasuresDao(getSession()); - project = new ResourceModel(ResourceModel.SCOPE_PROJECT, "foo:bar", ResourceModel.QUALIFIER_PROJECT_TRUNK, null, "Foo"); - project.setName("project name"); - getSession().save(project); - } - - @Test - public void shouldRegisterMetrics() { - Collection<Metric> newMetrics = createMetrics(); - service.registerMetrics(newMetrics); - - Collection<Metric> metrics = service.getEnabledMetrics(); - assertThat(metrics.size(), is(newMetrics.size())); - } - - private Collection<Metric> createMetrics() { - Metric m1 = new Metric("metric1"); - m1.setEnabled(false); - - Metric m2 = new Metric("metric2"); - m2.setEnabled(true); - - Metric m3 = new Metric("metric3"); - m3.setEnabled(false); - - Metric m4 = new Metric("metric4"); - m4.setEnabled(true); - - Metric m5 = new Metric("metric5"); - m5.setEnabled(true); - - return Arrays.asList(m1, m2, m3, m4, m5); - } -} |