From 3cc3f64462d9e06baa8436023da0ee2546b0cb35 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Wed, 31 Oct 2012 15:35:27 +0100 Subject: [PATCH] SONAR-3895 export violations indexed by resource --- .../org/sonar/batch/local/DryRunExporter.java | 83 ++++++++++--------- .../sonar/batch/local/DryRunExporterTest.java | 32 +++++-- 2 files changed, 70 insertions(+), 45 deletions(-) diff --git a/sonar-batch/src/main/java/org/sonar/batch/local/DryRunExporter.java b/sonar-batch/src/main/java/org/sonar/batch/local/DryRunExporter.java index 432228ef477..8926eecfb28 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/local/DryRunExporter.java +++ b/sonar-batch/src/main/java/org/sonar/batch/local/DryRunExporter.java @@ -20,18 +20,13 @@ package org.sonar.batch.local; import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Charsets; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.google.common.io.Closeables; -import com.google.common.io.Files; -import com.google.gson.Gson; import com.google.gson.stream.JsonWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.BatchComponent; import org.sonar.api.batch.SensorContext; +import org.sonar.api.platform.Server; import org.sonar.api.resources.ProjectFileSystem; import org.sonar.api.resources.Resource; import org.sonar.api.rules.Violation; @@ -39,12 +34,13 @@ import org.sonar.api.utils.SonarException; import org.sonar.batch.bootstrap.DryRun; import org.sonar.batch.index.DefaultIndex; +import java.io.BufferedWriter; import java.io.File; +import java.io.FileWriter; import java.io.IOException; -import java.io.StringWriter; +import java.io.Writer; import java.util.Collection; import java.util.List; -import java.util.Map; /** * @since 3.4 @@ -55,11 +51,13 @@ public class DryRunExporter implements BatchComponent { private final DryRun dryRun; private final DefaultIndex sonarIndex; private final ProjectFileSystem projectFileSystem; + private final Server server; - public DryRunExporter(DryRun dryRun, DefaultIndex sonarIndex, ProjectFileSystem projectFileSystem) { + public DryRunExporter(DryRun dryRun, DefaultIndex sonarIndex, ProjectFileSystem projectFileSystem, Server server) { this.dryRun = dryRun; this.sonarIndex = sonarIndex; this.projectFileSystem = projectFileSystem; + this.server = server; } public void execute(SensorContext context) { @@ -67,61 +65,66 @@ public class DryRunExporter implements BatchComponent { return; } - String json = getResultsAsJson(sonarIndex.getResources()); - exportResults(json); + exportResults(sonarIndex.getResources()); } - private void exportResults(String json) { + private void exportResults(Collection resources) { File exportFile = new File(projectFileSystem.getSonarWorkingDirectory(), dryRun.getExportPath()); LOG.info("Exporting DryRun results to " + exportFile.getAbsolutePath()); + Writer output = null; try { - Files.write(json, exportFile, Charsets.UTF_8); + output = new BufferedWriter(new FileWriter(exportFile)); + writeJson(resources, output); + output.flush(); } catch (IOException e) { throw new SonarException("Unable to write DryRun results in file " + exportFile.getAbsolutePath()); + } finally { + Closeables.closeQuietly(output); } } @VisibleForTesting - String getResultsAsJson(Collection resources) { - Gson gson = new Gson(); - - StringWriter output = new StringWriter(); - - JsonWriter writer = null; + void writeJson(Collection resources, Writer output) { + JsonWriter json = null; try { - writer = new JsonWriter(output); - writer.beginArray(); + json = new JsonWriter(output); + json.setSerializeNulls(false); + + json.beginObject() + .name("version").value(server.getVersion()) + .name("violations_per_resource") + .beginObject(); for (Resource resource : resources) { - List> resourceViolations = Lists.newArrayList(); - for (Violation violation : getViolations(resource)) { - Map json = Maps.newLinkedHashMap(); - if (null != violation.getLineId()) { - json.put("line", violation.getLineId()); - } - json.put("message", violation.getMessage()); - json.put("severity", violation.getSeverity().name()); - json.put("rule_key", violation.getRule().getKey()); - json.put("rule_name", violation.getRule().getName()); - resourceViolations.add(json); + List violations = getViolations(resource); + if (violations.isEmpty()) { + continue; } - Map obj = ImmutableMap.of( - "resource", resource.getKey(), - "violations", resourceViolations); + json.name(resource.getKey()) + .beginArray(); + + for (Violation violation : violations) { + json.beginObject() + .name("line").value(violation.getLineId()) + .name("message").value(violation.getMessage()) + .name("severity").value(violation.getSeverity().name()) + .name("rule_key").value(violation.getRule().getKey()) + .name("rule_name").value(violation.getRule().getName()) + .endObject(); + } - gson.toJson(obj, Map.class, writer); + json.endArray(); } - writer.endArray(); + json.endObject() + .endObject(); } catch (IOException e) { throw new SonarException("Unable to export results", e); } finally { - Closeables.closeQuietly(writer); + Closeables.closeQuietly(json); } - - return output.toString(); } @VisibleForTesting diff --git a/sonar-batch/src/test/java/org/sonar/batch/local/DryRunExporterTest.java b/sonar-batch/src/test/java/org/sonar/batch/local/DryRunExporterTest.java index d2dc09d5b82..1fb06100ad3 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/local/DryRunExporterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/local/DryRunExporterTest.java @@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableSet; import org.junit.Before; import org.junit.Test; import org.sonar.api.batch.SensorContext; +import org.sonar.api.platform.Server; import org.sonar.api.resources.ProjectFileSystem; import org.sonar.api.resources.Resource; import org.sonar.api.rules.Rule; @@ -32,6 +33,7 @@ import org.sonar.batch.bootstrap.DryRun; import org.sonar.batch.index.DefaultIndex; import org.sonar.java.api.JavaClass; +import java.io.StringWriter; import java.util.Arrays; import static org.fest.assertions.Assertions.assertThat; @@ -50,10 +52,11 @@ public class DryRunExporterTest { Resource resource = JavaClass.create("KEY"); Violation violation = mock(Violation.class); ProjectFileSystem projectFileSystem = mock(ProjectFileSystem.class); + Server server = mock(Server.class); @Before public void setUp() { - dryRunExporter = spy(new DryRunExporter(dryRun, sonarIndex, projectFileSystem)); + dryRunExporter = spy(new DryRunExporter(dryRun, sonarIndex, projectFileSystem, server)); } @Test @@ -66,6 +69,7 @@ public class DryRunExporterTest { @Test public void should_export_violations() { when(dryRun.isEnabled()).thenReturn(true); + when(server.getVersion()).thenReturn("3.4"); when(violation.getResource()).thenReturn(resource); when(violation.getLineId()).thenReturn(1); when(violation.getMessage()).thenReturn("VIOLATION"); @@ -73,15 +77,18 @@ public class DryRunExporterTest { when(violation.getSeverity()).thenReturn(RulePriority.INFO); doReturn(Arrays.asList(violation)).when(dryRunExporter).getViolations(resource); - String json = dryRunExporter.getResultsAsJson(ImmutableSet.of(resource)); + StringWriter output = new StringWriter(); + dryRunExporter.writeJson(ImmutableSet.of(resource), output); + String json = output.toString(); assertThat(json).isEqualTo( - "[{\"resource\":\"KEY\",\"violations\":[{\"line\":1,\"message\":\"VIOLATION\",\"severity\":\"INFO\",\"rule_key\":\"RULE_KEY\",\"rule_name\":\"RULE_NAME\"}]}]"); + "{\"version\":\"3.4\",\"violations_per_resource\":{\"KEY\":[{\"line\":1,\"message\":\"VIOLATION\",\"severity\":\"INFO\",\"rule_key\":\"RULE_KEY\",\"rule_name\":\"RULE_NAME\"}]}}"); } @Test public void should_export_violation_with_no_line() { when(dryRun.isEnabled()).thenReturn(true); + when(server.getVersion()).thenReturn("3.4"); when(violation.getResource()).thenReturn(resource); when(violation.getLineId()).thenReturn(null); when(violation.getMessage()).thenReturn("VIOLATION"); @@ -89,9 +96,24 @@ public class DryRunExporterTest { when(violation.getSeverity()).thenReturn(RulePriority.INFO); doReturn(Arrays.asList(violation)).when(dryRunExporter).getViolations(resource); - String json = dryRunExporter.getResultsAsJson(ImmutableSet.of(resource)); + StringWriter output = new StringWriter(); + dryRunExporter.writeJson(ImmutableSet.of(resource), output); + String json = output.toString(); assertThat(json).isEqualTo( - "[{\"resource\":\"KEY\",\"violations\":[{\"message\":\"VIOLATION\",\"severity\":\"INFO\",\"rule_key\":\"RULE_KEY\",\"rule_name\":\"RULE_NAME\"}]}]"); + "{\"version\":\"3.4\",\"violations_per_resource\":{\"KEY\":[{\"message\":\"VIOLATION\",\"severity\":\"INFO\",\"rule_key\":\"RULE_KEY\",\"rule_name\":\"RULE_NAME\"}]}}"); + } + + @Test + public void should_ignore_resources_without_violations() { + when(dryRun.isEnabled()).thenReturn(true); + when(server.getVersion()).thenReturn("3.4"); + doReturn(Arrays. asList()).when(dryRunExporter).getViolations(resource); + + StringWriter output = new StringWriter(); + dryRunExporter.writeJson(ImmutableSet.of(resource), output); + String json = output.toString(); + + assertThat(json).isEqualTo("{\"version\":\"3.4\",\"violations_per_resource\":{}}"); } } -- 2.39.5