From 6ce6cc598fdcd6e3d6eb662b47668b0c6b898f3d Mon Sep 17 00:00:00 2001 From: simonbrandhof Date: Mon, 29 Nov 2010 17:00:54 +0000 Subject: [PATCH] SONAR-249 improve core components to load rules and metrics --- .../DifferentialValueDecorator.java | 15 ++-- .../dbcleaner/purges/PurgeRuleMeasures.java | 5 +- ...ugsRuleFinder.java => FakeRuleFinder.java} | 16 ++-- .../findbugs/FindbugsProfileImporterTest.java | 23 +++--- .../plugins/findbugs/FindbugsSensorTest.java | 14 ++-- .../SonarWayWithFindbugsProfileTest.java | 2 +- .../plugins/pmd/PmdProfileExporterTest.java | 10 ++- .../src/main/java/org/sonar/batch/Batch.java | 5 +- .../org/sonar/batch/DefaultTimeMachine.java | 25 +++++- .../java/org/sonar/batch/ProjectBatch.java | 4 +- .../org/sonar/batch/index/DefaultIndex.java | 2 +- .../sonar/batch/index/MeasurePersister.java | 16 +++- .../sonar/batch/index/ViolationPersister.java | 29 ++----- .../batch/index/MeasurePersisterTest.java | 3 +- .../batch/index/ViolationPersisterTest.java | 3 +- .../core/components/CacheMetricFinder.java | 32 ++++---- .../core/components/CacheRuleFinder.java | 74 ++++++++++++++++++ .../DefaultModelFinder.java | 2 +- .../DefaultRuleFinder.java | 18 ++++- .../components/CacheMetricFinderTest.java | 65 ++++++++++++++++ .../core/components/CacheRuleFinderTest.java | 61 +++++++++++++++ .../DefaultModelFinderTest.java | 3 +- .../DefaultRuleFinderTest.java | 52 ++++++++----- .../ModelTest.java | 7 +- .../CacheMetricFinderTest/shared.xml | 12 +++ .../DefaultModelFinderTest/shared.xml | 0 .../DefaultRuleFinderTest/shared.xml | 0 .../ModelTest/saveModelAndCharacteristics.xml | 0 .../ModelTest/testGraphOfCharacteristics.xml | 0 .../ModelTest/testTreeOfCharacteristics.xml | 0 .../api/database/model/MeasureModel.java | 76 ++----------------- .../org/sonar/api/measures/MetricFinder.java | 4 +- .../java/org/sonar/api/rules/RuleFinder.java | 1 + .../org/sonar/server/platform/Platform.java | 4 +- 34 files changed, 394 insertions(+), 189 deletions(-) rename plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/{FindbugsRuleFinder.java => FakeRuleFinder.java} (89%) rename sonar-batch/src/main/java/org/sonar/batch/DefaultMetricFinder.java => sonar-core/src/main/java/org/sonar/core/components/CacheMetricFinder.java (62%) create mode 100644 sonar-core/src/main/java/org/sonar/core/components/CacheRuleFinder.java rename sonar-core/src/main/java/org/sonar/core/{qualitymodel => components}/DefaultModelFinder.java (97%) rename sonar-core/src/main/java/org/sonar/core/{rule => components}/DefaultRuleFinder.java (85%) create mode 100644 sonar-core/src/test/java/org/sonar/core/components/CacheMetricFinderTest.java create mode 100644 sonar-core/src/test/java/org/sonar/core/components/CacheRuleFinderTest.java rename sonar-core/src/test/java/org/sonar/core/{qualitymodel => components}/DefaultModelFinderTest.java (94%) rename sonar-core/src/test/java/org/sonar/core/{rule => components}/DefaultRuleFinderTest.java (55%) rename sonar-core/src/test/java/org/sonar/core/{qualitymodel => components}/ModelTest.java (94%) create mode 100644 sonar-core/src/test/resources/org/sonar/core/components/CacheMetricFinderTest/shared.xml rename sonar-core/src/test/resources/org/sonar/core/{qualitymodel => components}/DefaultModelFinderTest/shared.xml (100%) rename sonar-core/src/test/resources/org/sonar/core/{rule => components}/DefaultRuleFinderTest/shared.xml (100%) rename sonar-core/src/test/resources/org/sonar/core/{qualitymodel => components}/ModelTest/saveModelAndCharacteristics.xml (100%) rename sonar-core/src/test/resources/org/sonar/core/{qualitymodel => components}/ModelTest/testGraphOfCharacteristics.xml (100%) rename sonar-core/src/test/resources/org/sonar/core/{qualitymodel => components}/ModelTest/testTreeOfCharacteristics.xml (100%) diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/DifferentialValueDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/DifferentialValueDecorator.java index 8ba04b4e621..2ece3f89ff1 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/DifferentialValueDecorator.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/DifferentialValueDecorator.java @@ -31,7 +31,6 @@ import org.sonar.api.qualitymodel.Characteristic; import org.sonar.api.resources.Project; import org.sonar.api.resources.Resource; import org.sonar.api.resources.ResourceUtils; -import org.sonar.api.rules.Rule; import org.sonar.api.rules.RulePriority; import java.util.Collection; @@ -142,7 +141,7 @@ public class DifferentialValueDecorator implements Decorator { // improvements : keep query in cache ? select only some columns ? // TODO support measure on rules and characteristics String hql = "select m from " + MeasureModel.class.getSimpleName() + " m, " + Snapshot.class.getSimpleName() + " s " + - "where m.snapshotId=s.id and m.metricId in (:metricIds) and m.rule=null and m.rulePriority=null and m.rulesCategoryId=null and m.characteristic=null " + "where m.snapshotId=s.id and m.metricId in (:metricIds) and m.ruleId=null and m.rulePriority=null and m.rulesCategoryId=null and m.characteristic=null " + "and (s.rootId=:rootSnapshotId or s.id=:rootSnapshotId) and s.resourceId=:resourceId and s.status=:status"; return session.createQuery(hql) .setParameter("metricIds", metricByIds.keySet()) @@ -159,14 +158,14 @@ public class DifferentialValueDecorator implements Decorator { static class MeasureKey { Integer metricId; - Rule rule; + Integer ruleId; Integer categoryId; RulePriority priority; Characteristic characteristic; MeasureKey(MeasureModel model) { - this.metricId = model.getMetricId(); - rule = model.getRule(); + metricId = model.getMetricId(); + ruleId = model.getRuleId(); categoryId = model.getRulesCategoryId(); priority = model.getRulePriority(); characteristic = model.getCharacteristic(); @@ -179,7 +178,7 @@ public class DifferentialValueDecorator implements Decorator { if (measure instanceof RuleMeasure) { RuleMeasure rm = (RuleMeasure) measure; categoryId = rm.getRuleCategory(); - rule = rm.getRule(); + ruleId = (rm.getRule()==null ? null : rm.getRule().getId()); priority = rm.getRulePriority(); } } @@ -196,7 +195,7 @@ public class DifferentialValueDecorator implements Decorator { return false; if (!metricId.equals(that.metricId)) return false; if (priority != that.priority) return false; - if (rule != null ? !rule.equals(that.rule) : that.rule != null) return false; + if (ruleId != null ? !ruleId.equals(that.ruleId) : that.ruleId != null) return false; return true; } @@ -204,7 +203,7 @@ public class DifferentialValueDecorator implements Decorator { @Override public int hashCode() { int result = metricId.hashCode(); - result = 31 * result + (rule != null ? rule.hashCode() : 0); + result = 31 * result + (ruleId != null ? ruleId.hashCode() : 0); result = 31 * result + (categoryId != null ? categoryId.hashCode() : 0); result = 31 * result + (priority != null ? priority.hashCode() : 0); result = 31 * result + (characteristic != null ? characteristic.hashCode() : 0); diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/purges/PurgeRuleMeasures.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/purges/PurgeRuleMeasures.java index d61ad812499..c0eb8f36207 100644 --- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/purges/PurgeRuleMeasures.java +++ b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/purges/PurgeRuleMeasures.java @@ -26,9 +26,8 @@ import org.sonar.plugins.dbcleaner.api.Purge; import org.sonar.plugins.dbcleaner.api.PurgeContext; import org.sonar.plugins.dbcleaner.api.PurgeUtils; -import java.util.List; - import javax.persistence.Query; +import java.util.List; /** * see SONAR-522 @@ -49,7 +48,7 @@ public final class PurgeRuleMeasures extends Purge { private void purge(Integer sid) { Query query = getSession().createQuery("SELECT m.id FROM " + MeasureModel.class.getSimpleName() + " m, " + Snapshot.class.getSimpleName() + " s WHERE s.id = m.snapshotId and " + - "(s.rootId=:rootSid OR s.id=:rootSid) and (m.rule is not null or m.rulesCategoryId is not null or m.rulePriority is not null)"); + "(s.rootId=:rootSid OR s.id=:rootSid) and (m.ruleId is not null or m.rulesCategoryId is not null or m.rulePriority is not null)"); query.setParameter("rootSid", sid); List measureIds = query.getResultList(); PurgeUtils.deleteMeasuresById(getSession(), measureIds); diff --git a/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsRuleFinder.java b/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FakeRuleFinder.java similarity index 89% rename from plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsRuleFinder.java rename to plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FakeRuleFinder.java index ab3af9d93a6..eae82300b29 100644 --- a/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsRuleFinder.java +++ b/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FakeRuleFinder.java @@ -19,26 +19,30 @@ */ package org.sonar.plugins.findbugs; -import java.util.Collection; -import java.util.List; - import org.sonar.api.rules.Rule; import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.RuleQuery; import org.sonar.api.rules.XMLRuleParser; -public class FindbugsRuleFinder implements RuleFinder { +import java.util.Collection; +import java.util.List; + +public class FakeRuleFinder implements RuleFinder { private final List findbugsRules; - public FindbugsRuleFinder() { + public FakeRuleFinder() { FindbugsRuleRepository repo = new FindbugsRuleRepository(new XMLRuleParser()); findbugsRules = repo.createRules(); - for(Rule rule : findbugsRules){ + for (Rule rule : findbugsRules) { rule.setRepositoryKey(FindbugsConstants.REPOSITORY_KEY); } } + public Rule findById(int ruleId) { + throw new UnsupportedOperationException(); + } + public Rule findByKey(String repositoryKey, String key) { for (Rule rule : findbugsRules) { if (rule.getKey().equals(key)) { diff --git a/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsProfileImporterTest.java b/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsProfileImporterTest.java index 9296f03613e..206ccdfc07d 100644 --- a/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsProfileImporterTest.java +++ b/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsProfileImporterTest.java @@ -19,16 +19,7 @@ */ package org.sonar.plugins.findbugs; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringReader; -import java.util.List; - +import com.thoughtworks.xstream.XStream; import org.apache.commons.io.IOUtils; import org.junit.Test; import org.sonar.api.profiles.RulesProfile; @@ -38,11 +29,19 @@ import org.sonar.plugins.findbugs.xml.FindBugsFilter; import org.sonar.plugins.findbugs.xml.Match; import org.sonar.test.TestUtils; -import com.thoughtworks.xstream.XStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.util.List; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.junit.Assert.assertThat; public class FindbugsProfileImporterTest { - private FindbugsProfileImporter importer = new FindbugsProfileImporter(new FindbugsRuleFinder()); + private FindbugsProfileImporter importer = new FindbugsProfileImporter(new FakeRuleFinder()); @Test public void shouldImportPatterns() throws IOException { diff --git a/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsSensorTest.java b/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsSensorTest.java index d5124bf0f1a..9cd16af6c98 100644 --- a/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsSensorTest.java +++ b/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/FindbugsSensorTest.java @@ -48,14 +48,14 @@ public class FindbugsSensorTest extends FindbugsTests { @Test public void shouldExecuteWhenSomeRulesAreActive() throws Exception { - FindbugsSensor sensor = new FindbugsSensor(createRulesProfileWithActiveRules(), new FindbugsRuleFinder(), null); + FindbugsSensor sensor = new FindbugsSensor(createRulesProfileWithActiveRules(), new FakeRuleFinder(), null); Project project = createProject(); assertTrue(sensor.shouldExecuteOnProject(project)); } @Test public void shouldExecuteWhenReuseExistingRulesConfig() throws Exception { - FindbugsSensor analyser = new FindbugsSensor(RulesProfile.create(), new FindbugsRuleFinder(), null); + FindbugsSensor analyser = new FindbugsSensor(RulesProfile.create(), new FakeRuleFinder(), null); Project pom = createProject(); when(pom.getReuseExistingRulesConfig()).thenReturn(true); assertTrue(analyser.shouldExecuteOnProject(pom)); @@ -63,7 +63,7 @@ public class FindbugsSensorTest extends FindbugsTests { @Test public void shouldNotExecuteWhenNoRulesAreActive() throws Exception { - FindbugsSensor analyser = new FindbugsSensor(RulesProfile.create(), new FindbugsRuleFinder(), null); + FindbugsSensor analyser = new FindbugsSensor(RulesProfile.create(), new FakeRuleFinder(), null); Project pom = createProject(); assertFalse(analyser.shouldExecuteOnProject(pom)); } @@ -72,7 +72,7 @@ public class FindbugsSensorTest extends FindbugsTests { public void shouldNotExecuteOnEar() { Project project = createProject(); when(project.getPom().getPackaging()).thenReturn("ear"); - FindbugsSensor analyser = new FindbugsSensor(createRulesProfileWithActiveRules(), new FindbugsRuleFinder(), null); + FindbugsSensor analyser = new FindbugsSensor(createRulesProfileWithActiveRules(), new FakeRuleFinder(), null); assertFalse(analyser.shouldExecuteOnProject(project)); } @@ -88,7 +88,7 @@ public class FindbugsSensorTest extends FindbugsTests { when(executor.execute()).thenReturn(xmlFile); when(context.getResource(any(Resource.class))).thenReturn(new JavaFile("org.sonar.MyClass")); - FindbugsSensor analyser = new FindbugsSensor(createRulesProfileWithActiveRules(), new FindbugsRuleFinder(), executor); + FindbugsSensor analyser = new FindbugsSensor(createRulesProfileWithActiveRules(), new FakeRuleFinder(), executor); analyser.analyse(project, context); verify(executor).execute(); @@ -116,7 +116,7 @@ public class FindbugsSensorTest extends FindbugsTests { when(project.getConfiguration()).thenReturn(conf); when(context.getResource(any(Resource.class))).thenReturn(new JavaFile("org.sonar.MyClass")); - FindbugsSensor analyser = new FindbugsSensor(createRulesProfileWithActiveRules(), new FindbugsRuleFinder(), executor); + FindbugsSensor analyser = new FindbugsSensor(createRulesProfileWithActiveRules(), new FakeRuleFinder(), executor); analyser.analyse(project, context); verify(executor, never()).execute(); @@ -144,7 +144,7 @@ public class FindbugsSensorTest extends FindbugsTests { when(project.getConfiguration()).thenReturn(conf); when(context.getResource(any(Resource.class))).thenReturn(new JavaFile("org.sonar.MyClass")); - FindbugsSensor analyser = new FindbugsSensor(createRulesProfileWithActiveRules(), new FindbugsRuleFinder(), executor); + FindbugsSensor analyser = new FindbugsSensor(createRulesProfileWithActiveRules(), new FakeRuleFinder(), executor); analyser.analyse(project, context); verify(context, never()).saveViolation(any(Violation.class)); diff --git a/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/SonarWayWithFindbugsProfileTest.java b/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/SonarWayWithFindbugsProfileTest.java index 881fbf9a36b..a21e3ccaecc 100644 --- a/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/SonarWayWithFindbugsProfileTest.java +++ b/plugins/sonar-findbugs-plugin/src/test/java/org/sonar/plugins/findbugs/SonarWayWithFindbugsProfileTest.java @@ -31,7 +31,7 @@ public class SonarWayWithFindbugsProfileTest { @Test public void shouldCreateProfile() { - FindbugsProfileImporter importer = new FindbugsProfileImporter(new FindbugsRuleFinder()); + FindbugsProfileImporter importer = new FindbugsProfileImporter(new FakeRuleFinder()); SonarWayWithFindbugsProfile sonarWayWithFindbugs = new SonarWayWithFindbugsProfile(importer); ValidationMessages validation = ValidationMessages.create(); RulesProfile profile = sonarWayWithFindbugs.createProfile(validation); diff --git a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java index c35e9440f45..a0a458758bf 100644 --- a/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java +++ b/plugins/sonar-pmd-plugin/src/test/java/org/sonar/plugins/pmd/PmdProfileExporterTest.java @@ -35,7 +35,7 @@ public class PmdProfileExporterTest { PmdRuleRepository repository = new PmdRuleRepository(fileSystem, new XMLRuleParser()); List rules = repository.createRules(); - RuleFinder ruleFinder = new PmdRuleFinder(rules); + RuleFinder ruleFinder = new FakeRuleFinder(rules); PmdProfileImporter importer = new PmdProfileImporter(ruleFinder); Reader reader = new StringReader(TestUtils.getResourceContent("/org/sonar/plugins/pmd/simple.xml")); RulesProfile rulesProfile = importer.importProfile(reader, ValidationMessages.create()); @@ -103,14 +103,18 @@ public class PmdProfileExporterTest { assertThat(rule.getProperty(PmdConstants.XPATH_EXPRESSION_PARAM).getValue(), is(xpathExpression)); } - private static class PmdRuleFinder implements RuleFinder { + private static class FakeRuleFinder implements RuleFinder { private List rules; - public PmdRuleFinder(List rules) { + public FakeRuleFinder(List rules) { this.rules = rules; } + public Rule findById(int ruleId) { + throw new UnsupportedOperationException(); + } + public Rule findByKey(String repositoryKey, String key) { throw new UnsupportedOperationException(); } 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 303d4d099b5..d6c5c6a8bd6 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/Batch.java +++ b/sonar-batch/src/main/java/org/sonar/batch/Batch.java @@ -30,6 +30,8 @@ import org.sonar.api.utils.HttpDownloader; import org.sonar.api.utils.IocContainer; import org.sonar.api.utils.ServerHttpClient; import org.sonar.batch.index.*; +import org.sonar.core.components.CacheMetricFinder; +import org.sonar.core.components.CacheRuleFinder; import org.sonar.core.plugin.JpaPluginDao; import org.sonar.jpa.dao.MeasuresDao; import org.sonar.jpa.session.DatabaseSessionProvider; @@ -71,7 +73,6 @@ 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(DefaultMetricFinder.class); batchContainer.as(Characteristics.CACHE).addComponent(DefaultIndex.class); batchContainer.as(Characteristics.CACHE).addComponent(DefaultPersistenceManager.class); batchContainer.as(Characteristics.CACHE).addComponent(DependencyPersister.class); @@ -87,6 +88,8 @@ public class Batch { batchContainer.as(Characteristics.CACHE).addComponent(ServerHttpClient.class); batchContainer.as(Characteristics.CACHE).addComponent(HttpDownloader.class); batchContainer.as(Characteristics.CACHE).addComponent(MeasuresDao.class); + batchContainer.as(Characteristics.CACHE).addComponent(CacheRuleFinder.class); + batchContainer.as(Characteristics.CACHE).addComponent(CacheMetricFinder.class); batchContainer.start(); ProjectTree projectTree = batchContainer.getComponent(ProjectTree.class); diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java index 86fe3f38b58..8aedf065a5e 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java +++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultTimeMachine.java @@ -31,10 +31,9 @@ import org.sonar.api.measures.Metric; import org.sonar.api.measures.MetricFinder; import org.sonar.api.resources.Resource; import org.sonar.batch.index.DefaultIndex; -import org.sonar.jpa.dao.MeasuresDao; -import java.util.*; import javax.persistence.Query; +import java.util.*; public class DefaultTimeMachine implements TimeMachine { @@ -56,7 +55,7 @@ public class DefaultTimeMachine implements TimeMachine { for (Object[] object : objects) { MeasureModel model = (MeasureModel) object[0]; - Measure measure = model.toMeasure(metricById.get(model.getMetricId())); + Measure measure = toMeasure(model, metricById.get(model.getMetricId())); measure.setDate((Date) object[1]); result.add(measure); } @@ -93,7 +92,7 @@ public class DefaultTimeMachine implements TimeMachine { 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 "); + sb.append(" AND m.ruleId IS NULL AND m.rulePriority IS NULL AND m.rulesCategoryId IS NULL "); if (!metricIds.isEmpty()) { sb.append(" AND m.metricId IN (:metricIds) "); params.put("metricIds", metricIds); @@ -136,4 +135,22 @@ public class DefaultTimeMachine implements TimeMachine { } return result; } + + static Measure toMeasure(MeasureModel model, Metric metric) { + // NOTE: measures on rule are not supported + Measure measure = new Measure(metric); + measure.setId(model.getId()); + measure.setDescription(model.getDescription()); + measure.setValue(model.getValue()); + measure.setData(model.getData(metric)); + measure.setAlertStatus(model.getAlertStatus()); + measure.setAlertText(model.getAlertText()); + measure.setTendency(model.getTendency()); + measure.setDiffValue1(model.getDiffValue1()); + measure.setDiffValue2(model.getDiffValue2()); + measure.setDiffValue3(model.getDiffValue3()); + measure.setUrl(model.getUrl()); + measure.setCharacteristic(model.getCharacteristic()); + return measure; + } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java b/sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java index d6843c900dd..104f7eb0660 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java +++ b/sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java @@ -38,8 +38,7 @@ import org.sonar.api.utils.SonarException; import org.sonar.batch.index.DefaultIndex; import org.sonar.batch.index.DefaultResourcePersister; import org.sonar.batch.phases.Phases; -import org.sonar.core.qualitymodel.DefaultModelFinder; -import org.sonar.core.rule.DefaultRuleFinder; +import org.sonar.core.components.DefaultModelFinder; import org.sonar.jpa.dao.*; import java.util.List; @@ -93,7 +92,6 @@ public class ProjectBatch { batchContainer.as(Characteristics.CACHE).addComponent(ViolationFilters.class); batchContainer.as(Characteristics.CACHE).addComponent(ResourceFilters.class); batchContainer.as(Characteristics.CACHE).addComponent(DefaultModelFinder.class); - batchContainer.as(Characteristics.CACHE).addComponent(DefaultRuleFinder.class); batchContainer.addAdapter(new ProfileProvider()); batchContainer.addAdapter(new CheckProfileProvider()); loadCoreComponents(batchContainer); 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 55dbfa90c64..fca1ee8f04b 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 @@ -238,7 +238,7 @@ public final class DefaultIndex extends SonarIndex { public Measure addMeasure(Resource resource, Measure measure) { Bucket bucket = getOrAddBucket(resource); if (!bucket.isExcluded()) { - Metric metric = metricFinder.find(measure.getMetricKey()); + Metric metric = metricFinder.findByKey(measure.getMetricKey()); if (metric == null) { throw new SonarException("Unknown metric: " + measure.getMetricKey()); } 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 c4e34052b4e..4b7c47b21fc 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 @@ -32,6 +32,9 @@ 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 org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; +import org.sonar.api.utils.SonarException; import java.util.Collection; import java.util.Map; @@ -42,10 +45,12 @@ public final class MeasurePersister { private SetMultimap unsavedMeasuresByResource = LinkedHashMultimap.create(); private DatabaseSession session; private ResourcePersister resourcePersister; + private RuleFinder ruleFinder; - public MeasurePersister(DatabaseSession session, ResourcePersister resourcePersister) { + public MeasurePersister(DatabaseSession session, ResourcePersister resourcePersister, RuleFinder ruleFinder) { this.session = session; this.resourcePersister = resourcePersister; + this.ruleFinder = ruleFinder; } public void setDelayedMode(boolean delayedMode) { @@ -136,7 +141,14 @@ public final class MeasurePersister { RuleMeasure ruleMeasure = (RuleMeasure) measure; merge.setRulesCategoryId(ruleMeasure.getRuleCategory()); merge.setRulePriority(ruleMeasure.getRulePriority()); - merge.setRule(ruleMeasure.getRule()); + if (ruleMeasure.getRule()!=null) { + Rule ruleWithId = ruleFinder.findByKey(ruleMeasure.getRule().getRepositoryKey(), ruleMeasure.getRule().getKey()); + if (ruleWithId!=null) { + merge.setRuleId(ruleWithId.getId()); + } else { + throw new SonarException("Can not save a measure with unknown rule " + ruleMeasure); + } + } } return merge; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java index f5d2e9661c8..934aaadb7bd 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/ViolationPersister.java @@ -19,29 +19,28 @@ */ 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.resources.Resource; import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.Violation; -import org.sonar.api.utils.SonarException; import java.util.Collections; import java.util.List; -import java.util.Map; public final class ViolationPersister { private DatabaseSession session; private ResourcePersister resourcePersister; - private Map ruleIds = Maps.newHashMap(); + private RuleFinder ruleFinder; - public ViolationPersister(DatabaseSession session, ResourcePersister resourcePersister) { + public ViolationPersister(DatabaseSession session, ResourcePersister resourcePersister, RuleFinder ruleFinder) { this.session = session; this.resourcePersister = resourcePersister; + this.ruleFinder = ruleFinder; } public List getPreviousViolations(Resource resource) { @@ -76,28 +75,12 @@ public final class ViolationPersister { } private RuleFailureModel mergeModel(Violation violation, RuleFailureModel merge) { - merge.setRuleId(getRuleId(violation.getRule())); + Rule rule = ruleFinder.findByKey(violation.getRule().getRepositoryKey(), violation.getRule().getKey()); + merge.setRuleId(rule.getId()); merge.setPriority(violation.getPriority()); merge.setLine(violation.getLineId()); merge.setMessage(violation.getMessage()); merge.setCost(violation.getCost()); return merge; } - - private Integer getRuleId(Rule rule) { - Integer ruleId = ruleIds.get(rule); - if (ruleId == null) { - ruleId = rule.getId(); - 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; - } } 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 8d847fe0c73..5c556b8a53a 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 @@ -31,6 +31,7 @@ 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.core.components.DefaultRuleFinder; import org.sonar.jpa.test.AbstractDbUnitTestCase; import java.util.List; @@ -63,7 +64,7 @@ public class MeasurePersisterTest extends AbstractDbUnitTestCase { when(resourcePersister.saveResource((Project) anyObject(), eq(aPackage))).thenReturn(packageSnapshot); when(resourcePersister.getSnapshot(project)).thenReturn(projectSnapshot); when(resourcePersister.getSnapshot(aPackage)).thenReturn(packageSnapshot); - measurePersister = new MeasurePersister(getSession(), resourcePersister); + measurePersister = new MeasurePersister(getSession(), resourcePersister, new DefaultRuleFinder(getSessionFactory())); } @Test diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java index 0c6b898813d..f4b3164345f 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/ViolationPersisterTest.java @@ -28,6 +28,7 @@ import org.sonar.api.resources.Project; import org.sonar.api.rules.Rule; import org.sonar.api.rules.RulePriority; import org.sonar.api.rules.Violation; +import org.sonar.core.components.DefaultRuleFinder; import org.sonar.jpa.test.AbstractDbUnitTestCase; import java.util.List; @@ -55,7 +56,7 @@ public class ViolationPersisterTest extends AbstractDbUnitTestCase { when(resourcePersister.saveResource((Project) anyObject(), eq(javaFile))).thenReturn(snapshot); when(resourcePersister.getPreviousLastSnapshot(snapshot)).thenReturn(snapshot); when(resourcePersister.getSnapshot(javaFile)).thenReturn(snapshot); - violationPersister = new ViolationPersister(getSession(), resourcePersister); + violationPersister = new ViolationPersister(getSession(), resourcePersister, new DefaultRuleFinder(getSessionFactory())); } @Test diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultMetricFinder.java b/sonar-core/src/main/java/org/sonar/core/components/CacheMetricFinder.java similarity index 62% rename from sonar-batch/src/main/java/org/sonar/batch/DefaultMetricFinder.java rename to sonar-core/src/main/java/org/sonar/core/components/CacheMetricFinder.java index b0c7f01c9c5..fa125dc9da1 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/DefaultMetricFinder.java +++ b/sonar-core/src/main/java/org/sonar/core/components/CacheMetricFinder.java @@ -17,42 +17,48 @@ * 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.core.components; 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 org.sonar.jpa.session.DatabaseSessionFactory; import java.util.Collection; import java.util.List; import java.util.Map; -public final class DefaultMetricFinder implements MetricFinder { +public final class CacheMetricFinder implements MetricFinder { - private DatabaseSession session; - private Map metrics = Maps.newHashMap(); + private DatabaseSessionFactory sessionFactory; + private Map metricsByKey = Maps.newLinkedHashMap(); + private Map metricsById = Maps.newLinkedHashMap(); - public DefaultMetricFinder(DatabaseSession session) { - this.session = session; + public CacheMetricFinder(DatabaseSessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; } public void start() { - List list = session.getResults(Metric.class, "enabled", true); + List list = sessionFactory.getSession().getResults(Metric.class, "enabled", true); for (Metric metric : list) { - metrics.put(metric.getKey(), metric); + metricsByKey.put(metric.getKey(), metric); + metricsById.put(metric.getId(), metric); } } - public Metric find(String key) { - return metrics.get(key); + public Metric findById(int metricId) { + return metricsById.get(metricId); + } + + public Metric findByKey(String key) { + return metricsByKey.get(key); } public Collection findAll(List metricKeys) { List result = Lists.newLinkedList(); for (String metricKey : metricKeys) { - Metric metric = find(metricKey); + Metric metric = findByKey(metricKey); if (metric != null) { result.add(metric); } @@ -61,6 +67,6 @@ public final class DefaultMetricFinder implements MetricFinder { } public Collection findAll() { - return metrics.values(); + return metricsByKey.values(); } } diff --git a/sonar-core/src/main/java/org/sonar/core/components/CacheRuleFinder.java b/sonar-core/src/main/java/org/sonar/core/components/CacheRuleFinder.java new file mode 100644 index 00000000000..1e0b747bb61 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/components/CacheRuleFinder.java @@ -0,0 +1,74 @@ +/* + * 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.core.components; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Maps; +import org.sonar.api.rules.Rule; +import org.sonar.jpa.session.DatabaseSessionFactory; + +import java.util.Map; + +public final class CacheRuleFinder extends DefaultRuleFinder { + + private BiMap rulesById = HashBiMap.create(); + private Map> rulesByKey = Maps.newHashMap(); + + public CacheRuleFinder(DatabaseSessionFactory sessionFactory) { + super(sessionFactory); + } + + @Override + public Rule findById(int ruleId) { + Rule rule = rulesById.get(ruleId); + if (rule==null) { + rule = doFindById(ruleId); + addToCache(rule); + } + return rule; + } + + @Override + public Rule findByKey(String repositoryKey, String key) { + Map repoRules = rulesByKey.get(repositoryKey); + Rule rule = null; + if (repoRules!=null) { + rule = repoRules.get(key); + } + if (rule == null) { + rule = doFindByKey(repositoryKey, key); + addToCache(rule); + } + return rule; + } + + private void addToCache(Rule rule) { + if (rule != null) { + rulesById.put(rule.getId(), rule); + Map repoRules = rulesByKey.get(rule.getKey()); + if (repoRules==null) { + repoRules = Maps.newHashMap(); + rulesByKey.put(rule.getRepositoryKey(), repoRules); + } + repoRules.put(rule.getKey(), rule); + } + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/qualitymodel/DefaultModelFinder.java b/sonar-core/src/main/java/org/sonar/core/components/DefaultModelFinder.java similarity index 97% rename from sonar-core/src/main/java/org/sonar/core/qualitymodel/DefaultModelFinder.java rename to sonar-core/src/main/java/org/sonar/core/components/DefaultModelFinder.java index 5606e5e0907..a7a04c7cf24 100644 --- a/sonar-core/src/main/java/org/sonar/core/qualitymodel/DefaultModelFinder.java +++ b/sonar-core/src/main/java/org/sonar/core/components/DefaultModelFinder.java @@ -17,7 +17,7 @@ * License along with Sonar; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 */ -package org.sonar.core.qualitymodel; +package org.sonar.core.components; import org.sonar.api.database.DatabaseSession; import org.sonar.api.qualitymodel.Model; diff --git a/sonar-core/src/main/java/org/sonar/core/rule/DefaultRuleFinder.java b/sonar-core/src/main/java/org/sonar/core/components/DefaultRuleFinder.java similarity index 85% rename from sonar-core/src/main/java/org/sonar/core/rule/DefaultRuleFinder.java rename to sonar-core/src/main/java/org/sonar/core/components/DefaultRuleFinder.java index 6a167b180f7..3c0d50e7bcd 100644 --- a/sonar-core/src/main/java/org/sonar/core/rule/DefaultRuleFinder.java +++ b/sonar-core/src/main/java/org/sonar/core/components/DefaultRuleFinder.java @@ -17,7 +17,7 @@ * License along with Sonar; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 */ -package org.sonar.core.rule; +package org.sonar.core.components; import org.apache.commons.lang.StringUtils; import org.sonar.api.database.DatabaseSession; @@ -39,17 +39,29 @@ public class DefaultRuleFinder implements RuleFinder { this.sessionFactory = sessionFactory; } + public Rule findById(int ruleId) { + return doFindById(ruleId); + } + + protected final Rule doFindById(int ruleId) { + return sessionFactory.getSession().getSingleResult(Rule.class, "id", ruleId, "enabled", true); + } + public Rule findByKey(String repositoryKey, String key) { + return doFindByKey(repositoryKey, key); + } + + protected final Rule doFindByKey(String repositoryKey, String key) { return sessionFactory.getSession().getSingleResult(Rule.class, "pluginName", repositoryKey, "key", key, "enabled", true); } - public Rule find(RuleQuery query) { + public final Rule find(RuleQuery query) { DatabaseSession session = sessionFactory.getSession(); return (Rule)session.getSingleResult(createHqlQuery(session, query), null); } - public Collection findAll(RuleQuery query) { + public final Collection findAll(RuleQuery query) { DatabaseSession session = sessionFactory.getSession(); return createHqlQuery(session, query).getResultList(); } diff --git a/sonar-core/src/test/java/org/sonar/core/components/CacheMetricFinderTest.java b/sonar-core/src/test/java/org/sonar/core/components/CacheMetricFinderTest.java new file mode 100644 index 00000000000..a67fd0cf713 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/components/CacheMetricFinderTest.java @@ -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.core.components; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +import java.util.Arrays; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNull.nullValue; +import static org.junit.Assert.assertThat; + + +public class CacheMetricFinderTest extends AbstractDbUnitTestCase { + + private CacheMetricFinder finder; + + @Before + public void initFinder() { + setupData("shared"); + finder = new CacheMetricFinder(getSessionFactory()); + finder.start(); + } + + @Test + public void shouldFindAll() { + assertThat(finder.findAll().size(), is(2)); + } + + @Test + public void shouldFindByKeys() { + assertThat(finder.findAll(Arrays.asList("ncloc", "foo", "coverage")).size(), is(2)); + } + + @Test + public void shouldFindById() { + assertThat(finder.findById(1).getKey(), is("ncloc")); + assertThat(finder.findById(3), nullValue()); + } + + @Test + public void shouldFindByKey() { + assertThat(finder.findByKey("ncloc").getKey(), is("ncloc")); + assertThat(finder.findByKey("disabled"), nullValue()); + } +} diff --git a/sonar-core/src/test/java/org/sonar/core/components/CacheRuleFinderTest.java b/sonar-core/src/test/java/org/sonar/core/components/CacheRuleFinderTest.java new file mode 100644 index 00000000000..0eb9d239161 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/components/CacheRuleFinderTest.java @@ -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.core.components; + +import org.junit.Test; +import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; +import org.sonar.jpa.test.AbstractDbUnitTestCase; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNull.notNullValue; +import static org.junit.Assert.assertThat; + +public class CacheRuleFinderTest extends AbstractDbUnitTestCase { + + @Test + public void shouldCacheFindById() { + setupData("shared"); + RuleFinder finder = new CacheRuleFinder(getSessionFactory()); + assertThat(finder.findById(3).getConfigKey(), is("Checker/Treewalker/AnnotationUseStyleCheck")); + + deleteRules(); + + assertThat(finder.findById(3), notNullValue()); + } + + @Test + public void shouldCacheFindByKey() { + setupData("shared"); + RuleFinder finder = new CacheRuleFinder(getSessionFactory()); + Rule rule = finder.findByKey("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck"); + assertThat(rule.getConfigKey(), is("Checker/Treewalker/AnnotationUseStyleCheck")); + + deleteRules(); + + rule = finder.findByKey("checkstyle", "com.puppycrawl.tools.checkstyle.checks.annotation.AnnotationUseStyleCheck"); + assertThat(rule, notNullValue()); + } + + private void deleteRules() { + getSession().createQuery("delete " + Rule.class.getSimpleName()).executeUpdate(); + getSession().commit(); + } +} diff --git a/sonar-core/src/test/java/org/sonar/core/qualitymodel/DefaultModelFinderTest.java b/sonar-core/src/test/java/org/sonar/core/components/DefaultModelFinderTest.java similarity index 94% rename from sonar-core/src/test/java/org/sonar/core/qualitymodel/DefaultModelFinderTest.java rename to sonar-core/src/test/java/org/sonar/core/components/DefaultModelFinderTest.java index 9069fab38f4..222bf4053ed 100644 --- a/sonar-core/src/test/java/org/sonar/core/qualitymodel/DefaultModelFinderTest.java +++ b/sonar-core/src/test/java/org/sonar/core/components/DefaultModelFinderTest.java @@ -17,10 +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.core.qualitymodel; +package org.sonar.core.components; import org.junit.Test; import org.sonar.api.qualitymodel.Model; +import org.sonar.core.components.DefaultModelFinder; import org.sonar.jpa.test.AbstractDbUnitTestCase; import static org.junit.Assert.assertNotNull; diff --git a/sonar-core/src/test/java/org/sonar/core/rule/DefaultRuleFinderTest.java b/sonar-core/src/test/java/org/sonar/core/components/DefaultRuleFinderTest.java similarity index 55% rename from sonar-core/src/test/java/org/sonar/core/rule/DefaultRuleFinderTest.java rename to sonar-core/src/test/java/org/sonar/core/components/DefaultRuleFinderTest.java index c80573be1c0..7d2c2b8176a 100644 --- a/sonar-core/src/test/java/org/sonar/core/rule/DefaultRuleFinderTest.java +++ b/sonar-core/src/test/java/org/sonar/core/components/DefaultRuleFinderTest.java @@ -17,10 +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.core.rule; +package org.sonar.core.components; import org.junit.Test; import org.sonar.api.rules.Rule; +import org.sonar.api.rules.RuleFinder; import org.sonar.api.rules.RuleQuery; import org.sonar.jpa.test.AbstractDbUnitTestCase; @@ -28,35 +29,48 @@ import java.util.Collection; import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; +import static org.hamcrest.core.IsNull.nullValue; +import static org.junit.Assert.*; public class DefaultRuleFinderTest extends AbstractDbUnitTestCase { @Test - public void findByKey() { + public void shouldFindById() { setupData("shared"); - DefaultRuleFinder provider = new DefaultRuleFinder(getSessionFactory()); - Rule rule = provider.findByKey("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"); + RuleFinder finder = new DefaultRuleFinder(getSessionFactory()); + assertThat(finder.findById(3).getConfigKey(), is("Checker/Treewalker/AnnotationUseStyleCheck")); + } + + @Test + public void shouldNotFindDisabledRuleById() { + setupData("shared"); + RuleFinder finder = new DefaultRuleFinder(getSessionFactory()); + assertThat(finder.findById(2), nullValue()); + } + + @Test + public void shouldFindByKey() { + setupData("shared"); + RuleFinder finder = new DefaultRuleFinder(getSessionFactory()); + Rule rule = finder.findByKey("checkstyle", "com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"); assertNotNull(rule); assertThat(rule.getKey(), is("com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck")); assertThat(rule.isEnabled(), is(true)); } @Test - public void findReturnsNullIfNoResults() { + public void findShouldReturnNullIfNoResults() { setupData("shared"); - DefaultRuleFinder provider = new DefaultRuleFinder(getSessionFactory()); - assertNull(provider.findByKey("checkstyle", "unknown")); - assertNull(provider.find(RuleQuery.create().withRepositoryKey("checkstyle").withConfigKey("unknown"))); + RuleFinder finder = new DefaultRuleFinder(getSessionFactory()); + assertNull(finder.findByKey("checkstyle", "unknown")); + assertNull(finder.find(RuleQuery.create().withRepositoryKey("checkstyle").withConfigKey("unknown"))); } @Test public void findRepositoryRules() { setupData("shared"); - DefaultRuleFinder provider = new DefaultRuleFinder(getSessionFactory()); - Collection rules = provider.findAll(RuleQuery.create().withRepositoryKey("checkstyle")); + RuleFinder finder = new DefaultRuleFinder(getSessionFactory()); + Collection rules = finder.findAll(RuleQuery.create().withRepositoryKey("checkstyle")); assertNotNull(rules); assertThat(rules.size(), is(2)); // only enabled checkstyle rules } @@ -64,8 +78,8 @@ public class DefaultRuleFinderTest extends AbstractDbUnitTestCase { @Test public void findAllEnabled() { setupData("shared"); - DefaultRuleFinder provider = new DefaultRuleFinder(getSessionFactory()); - Collection rules = provider.findAll(RuleQuery.create()); + RuleFinder finder = new DefaultRuleFinder(getSessionFactory()); + Collection rules = finder.findAll(RuleQuery.create()); assertNotNull(rules); assertThat(rules.size(), is(3)); // only enabled checkstyle+pmd rules for (Rule rule : rules) { @@ -76,16 +90,16 @@ public class DefaultRuleFinderTest extends AbstractDbUnitTestCase { @Test public void doNotFindDisabledRules() { setupData("shared"); - DefaultRuleFinder provider = new DefaultRuleFinder(getSessionFactory()); - Rule rule = provider.findByKey("checkstyle", "DisabledCheck"); + RuleFinder finder = new DefaultRuleFinder(getSessionFactory()); + Rule rule = finder.findByKey("checkstyle", "DisabledCheck"); assertNull(rule); } @Test public void doNotFindUnknownRules() { setupData("shared"); - DefaultRuleFinder provider = new DefaultRuleFinder(getSessionFactory()); - Collection rules = provider.findAll(RuleQuery.create().withRepositoryKey("unknown_repository")); + RuleFinder finder = new DefaultRuleFinder(getSessionFactory()); + Collection rules = finder.findAll(RuleQuery.create().withRepositoryKey("unknown_repository")); assertThat(rules.size(), is(0)); } } diff --git a/sonar-core/src/test/java/org/sonar/core/qualitymodel/ModelTest.java b/sonar-core/src/test/java/org/sonar/core/components/ModelTest.java similarity index 94% rename from sonar-core/src/test/java/org/sonar/core/qualitymodel/ModelTest.java rename to sonar-core/src/test/java/org/sonar/core/components/ModelTest.java index 0c15154140a..b614dfbe8d2 100644 --- a/sonar-core/src/test/java/org/sonar/core/qualitymodel/ModelTest.java +++ b/sonar-core/src/test/java/org/sonar/core/components/ModelTest.java @@ -17,18 +17,15 @@ * License along with Sonar; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 */ -package org.sonar.core.qualitymodel; +package org.sonar.core.components; import org.junit.Test; import org.sonar.api.qualitymodel.Characteristic; import org.sonar.api.qualitymodel.Model; import org.sonar.jpa.test.AbstractDbUnitTestCase; -import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import static org.junit.internal.matchers.IsCollectionContaining.hasItems; public class ModelTest extends AbstractDbUnitTestCase { diff --git a/sonar-core/src/test/resources/org/sonar/core/components/CacheMetricFinderTest/shared.xml b/sonar-core/src/test/resources/org/sonar/core/components/CacheMetricFinderTest/shared.xml new file mode 100644 index 00000000000..85709bcbf98 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/components/CacheMetricFinderTest/shared.xml @@ -0,0 +1,12 @@ + + + \ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/qualitymodel/DefaultModelFinderTest/shared.xml b/sonar-core/src/test/resources/org/sonar/core/components/DefaultModelFinderTest/shared.xml similarity index 100% rename from sonar-core/src/test/resources/org/sonar/core/qualitymodel/DefaultModelFinderTest/shared.xml rename to sonar-core/src/test/resources/org/sonar/core/components/DefaultModelFinderTest/shared.xml diff --git a/sonar-core/src/test/resources/org/sonar/core/rule/DefaultRuleFinderTest/shared.xml b/sonar-core/src/test/resources/org/sonar/core/components/DefaultRuleFinderTest/shared.xml similarity index 100% rename from sonar-core/src/test/resources/org/sonar/core/rule/DefaultRuleFinderTest/shared.xml rename to sonar-core/src/test/resources/org/sonar/core/components/DefaultRuleFinderTest/shared.xml diff --git a/sonar-core/src/test/resources/org/sonar/core/qualitymodel/ModelTest/saveModelAndCharacteristics.xml b/sonar-core/src/test/resources/org/sonar/core/components/ModelTest/saveModelAndCharacteristics.xml similarity index 100% rename from sonar-core/src/test/resources/org/sonar/core/qualitymodel/ModelTest/saveModelAndCharacteristics.xml rename to sonar-core/src/test/resources/org/sonar/core/components/ModelTest/saveModelAndCharacteristics.xml diff --git a/sonar-core/src/test/resources/org/sonar/core/qualitymodel/ModelTest/testGraphOfCharacteristics.xml b/sonar-core/src/test/resources/org/sonar/core/components/ModelTest/testGraphOfCharacteristics.xml similarity index 100% rename from sonar-core/src/test/resources/org/sonar/core/qualitymodel/ModelTest/testGraphOfCharacteristics.xml rename to sonar-core/src/test/resources/org/sonar/core/components/ModelTest/testGraphOfCharacteristics.xml diff --git a/sonar-core/src/test/resources/org/sonar/core/qualitymodel/ModelTest/testTreeOfCharacteristics.xml b/sonar-core/src/test/resources/org/sonar/core/components/ModelTest/testTreeOfCharacteristics.xml similarity index 100% rename from sonar-core/src/test/resources/org/sonar/core/qualitymodel/ModelTest/testTreeOfCharacteristics.xml rename to sonar-core/src/test/resources/org/sonar/core/components/ModelTest/testTreeOfCharacteristics.xml diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureModel.java b/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureModel.java index 3a9c1a4bca0..e829e6e786e 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureModel.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/database/model/MeasureModel.java @@ -20,14 +20,9 @@ package org.sonar.api.database.model; import org.apache.commons.lang.builder.ToStringBuilder; -import org.hibernate.annotations.Cache; -import org.hibernate.annotations.CacheConcurrencyStrategy; import org.sonar.api.database.DatabaseSession; -import org.sonar.api.measures.Measure; import org.sonar.api.measures.Metric; -import org.sonar.api.measures.RuleMeasure; import org.sonar.api.qualitymodel.Characteristic; -import org.sonar.api.rules.Rule; import org.sonar.api.rules.RulePriority; import javax.persistence.*; @@ -74,10 +69,8 @@ public class MeasureModel implements Cloneable { @Column(name = "measure_date", updatable = true, nullable = true) private Date measureDate; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "rule_id") - @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) - private Rule rule; + @Column(name = "rule_id", updatable = true, nullable = true) + private Integer ruleId; @Column(name = "rules_category_id") private Integer rulesCategoryId; @@ -223,7 +216,7 @@ public class MeasureModel implements Cloneable { * @return whether the measure is about rule */ public boolean isRuleMeasure() { - return rule != null || rulePriority != null || rulesCategoryId != null; + return ruleId != null || rulePriority != null || rulesCategoryId != null; } /** @@ -261,11 +254,8 @@ public class MeasureModel implements Cloneable { return this; } - /** - * @return the rule - */ - public Rule getRule() { - return rule; + public Integer getRuleId() { + return ruleId; } /** @@ -273,8 +263,8 @@ public class MeasureModel implements Cloneable { * * @return the current object */ - public MeasureModel setRule(Rule rule) { - this.rule = rule; + public MeasureModel setRuleId(Integer ruleId) { + this.ruleId = ruleId; return this; } @@ -453,16 +443,6 @@ public class MeasureModel implements Cloneable { toString(); } - /** - * @return the rule id of the measure - */ - public Integer getRuleId() { - if (getRule() != null) { - return getRule().getId(); - } - return null; - } - /** * @return diffValue1 */ @@ -548,51 +528,11 @@ public class MeasureModel implements Cloneable { clone.setValue(getValue()); clone.setRulesCategoryId(getRulesCategoryId()); clone.setRulePriority(getRulePriority()); - clone.setRule(getRule()); + clone.setRuleId(getRuleId()); clone.setSnapshotId(getSnapshotId()); clone.setMeasureDate(getMeasureDate()); clone.setUrl(getUrl()); clone.setCharacteristic(getCharacteristic()); return clone; } - -/** - * True if other fields than 'value' are set. - */ - public boolean hasOptionalData() { - return getAlertStatus()!=null || - getAlertText()!=null || - getDescription()!=null || - getDiffValue1()!=null || - getDiffValue2()!=null || - getDiffValue3()!=null || - getMeasureData()!=null || - getTendency()!=null || - getUrl()!=null; - } - - /** - * @return a measure from the current object - */ - public Measure toMeasure(Metric metric) { - Measure measure; - if (isRuleMeasure()) { - measure = new RuleMeasure(metric, getRule(), getRulePriority(), getRulesCategoryId()); - } else { - measure = new Measure(metric); - } - measure.setId(getId()); - measure.setDescription(getDescription()); - measure.setValue(getValue()); - measure.setData(getData(metric)); - measure.setAlertStatus(getAlertStatus()); - measure.setAlertText(getAlertText()); - measure.setTendency(getTendency()); - measure.setDiffValue1(getDiffValue1()); - measure.setDiffValue2(getDiffValue2()); - measure.setDiffValue3(getDiffValue3()); - measure.setUrl(getUrl()); - measure.setCharacteristic(getCharacteristic()); - return measure; - } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MetricFinder.java b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MetricFinder.java index acd85a01e51..d05609c607a 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/measures/MetricFinder.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/measures/MetricFinder.java @@ -31,7 +31,9 @@ import java.util.List; */ public interface MetricFinder extends BatchComponent { - Metric find(String key); + Metric findById(int id); + + Metric findByKey(String key); Collection findAll(List metricKeys); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rules/RuleFinder.java b/sonar-plugin-api/src/main/java/org/sonar/api/rules/RuleFinder.java index 83581280908..b96249622e1 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/rules/RuleFinder.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/rules/RuleFinder.java @@ -29,6 +29,7 @@ import java.util.Collection; */ public interface RuleFinder extends BatchComponent, ServerComponent { + Rule findById(int ruleId); Rule findByKey(String repositoryKey, String key); Rule find(RuleQuery query); Collection findAll(RuleQuery query); diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 9cec2e85564..e17b9e1bac0 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -38,9 +38,9 @@ import org.sonar.api.rules.XMLRuleParser; import org.sonar.api.utils.HttpDownloader; import org.sonar.api.utils.IocContainer; import org.sonar.api.utils.TimeProfiler; +import org.sonar.core.components.DefaultModelFinder; +import org.sonar.core.components.DefaultRuleFinder; import org.sonar.core.plugin.JpaPluginDao; -import org.sonar.core.qualitymodel.DefaultModelFinder; -import org.sonar.core.rule.DefaultRuleFinder; import org.sonar.jpa.dao.*; import org.sonar.jpa.session.DatabaseSessionFactory; import org.sonar.jpa.session.DatabaseSessionProvider; -- 2.39.5