]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6277 Feed file sources in compute report
authorJulien HENRY <julien.henry@sonarsource.com>
Thu, 2 Apr 2015 16:13:52 +0000 (18:13 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Tue, 7 Apr 2015 15:21:33 +0000 (17:21 +0200)
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java
sonar-batch/src/main/java/org/sonar/batch/report/SourcePublisher.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
sonar-batch/src/test/java/org/sonar/batch/report/CoveragePublisherTest.java
sonar-batch/src/test/java/org/sonar/batch/report/SourcePublisherTest.java [new file with mode: 0644]
sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java

index 97b7e5f2caa7d32ed4d392d83dc6fa0f0c38b5dc..86ec1c53f6ee39b057ba62d9f16ecbc0ccc7b6cc 100644 (file)
@@ -118,4 +118,8 @@ public class BatchReportWriter {
     ProtobufUtil.writeMessagesToFile(coverageList, file);
   }
 
+  public File getSourceFile(int componentRef) {
+    return fileStructure.fileFor(FileStructure.Domain.SOURCE, componentRef);
+  }
+
 }
index 21df5a4cafbae5389feeacd808630c4fd74bf67b..e0add6865a0cabbe7dbb7639121c7d3ea26b9b2f 100644 (file)
@@ -27,22 +27,24 @@ import java.io.File;
 public class FileStructure {
 
   public enum Domain {
-    ISSUES("issues-"),
-    ISSUES_ON_DELETED("issues-deleted-"),
-    COMPONENT("component-"),
-    MEASURES("measures-"),
-    DUPLICATIONS("duplications-"),
-    SYNTAX_HIGHLIGHTING("syntax-highlighting-"),
-    SCM("scm-"),
-    SYMBOLS("symbol-"),
-    COVERAGE("coverage-"),
-    SOURCE("source-")
-    ;
-    
+    ISSUES("issues-", Domain.PB),
+    ISSUES_ON_DELETED("issues-deleted-", Domain.PB),
+    COMPONENT("component-", Domain.PB),
+    MEASURES("measures-", Domain.PB),
+    DUPLICATIONS("duplications-", Domain.PB),
+    SYNTAX_HIGHLIGHTING("syntax-highlighting-", Domain.PB),
+    SCM("scm-", Domain.PB),
+    SYMBOLS("symbol-", Domain.PB),
+    COVERAGE("coverage-", Domain.PB),
+    SOURCE("source-", ".txt");
+
+    private static final String PB = ".pb";
     private final String filePrefix;
+    private final String fileSuffix;
 
-    Domain(String filePrefix) {
+    Domain(String filePrefix, String fileSuffix) {
       this.filePrefix = filePrefix;
+      this.fileSuffix = fileSuffix;
     }
   }
 
@@ -60,7 +62,7 @@ public class FileStructure {
   }
 
   public File fileFor(Domain domain, int componentRef) {
-    return new File(dir, domain.filePrefix + componentRef + ".pb");
+    return new File(dir, domain.filePrefix + componentRef + domain.fileSuffix);
   }
 
 }
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/SourcePublisher.java b/sonar-batch/src/main/java/org/sonar/batch/report/SourcePublisher.java
new file mode 100644 (file)
index 0000000..ccb9168
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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.batch.report;
+
+import com.google.common.base.Charsets;
+import org.apache.commons.io.ByteOrderMark;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.BOMInputStream;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.batch.index.BatchResource;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+
+import java.io.*;
+
+public class SourcePublisher implements ReportPublisherStep {
+
+  private final ResourceCache resourceCache;
+
+  public SourcePublisher(ResourceCache resourceCache) {
+    this.resourceCache = resourceCache;
+  }
+
+  @Override
+  public void publish(BatchReportWriter writer) {
+    for (final BatchResource resource : resourceCache.all()) {
+      if (!resource.isFile()) {
+        continue;
+      }
+
+      DefaultInputFile inputFile = (DefaultInputFile) resource.inputPath();
+      File iofile = writer.getSourceFile(1);
+      int line = 0;
+      try (FileOutputStream output = new FileOutputStream(iofile); BOMInputStream bomIn = new BOMInputStream(new FileInputStream(inputFile.file()),
+        ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE);
+        BufferedReader reader = new BufferedReader(new InputStreamReader(bomIn, inputFile.charset()))) {
+        String lineStr = reader.readLine();
+        while (lineStr != null) {
+          IOUtils.write(lineStr, output, Charsets.UTF_8);
+          line++;
+          if (line < inputFile.lines()) {
+            IOUtils.write("\n", output, Charsets.UTF_8);
+          }
+          lineStr = reader.readLine();
+        }
+      } catch (IOException e) {
+        throw new IllegalStateException("Unable to store file source in the report", e);
+      }
+    }
+  }
+}
index 43ba3500126cc292bbdb97571f21f307871db6b6..12b0bc0f21d68eb3f9e20d4e3067ae7dbcc3aaf1 100644 (file)
@@ -188,6 +188,7 @@ public class ProjectScanContainer extends ComponentContainer {
       MeasuresPublisher.class,
       DuplicationsPublisher.class,
       CoveragePublisher.class,
+      SourcePublisher.class,
 
       ScanTaskObservers.class);
   }
index 2e1614bbdf1c1f2c73de9121bbe209b2afa5fdd1..347761203f72a4bf34e141817fe96e2d7869ec6f 100644 (file)
@@ -51,7 +51,6 @@ public class CoveragePublisherTest {
 
   private MeasureCache measureCache;
   private CoveragePublisher publisher;
-  private org.sonar.api.resources.File aFile = org.sonar.api.resources.File.create("org/foo/Bar.java");
 
   private org.sonar.api.resources.Resource sampleFile;
 
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/SourcePublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/SourcePublisherTest.java
new file mode 100644 (file)
index 0000000..824a6da
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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.batch.report;
+
+import com.google.common.base.Charsets;
+import org.apache.commons.io.FileUtils;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.resources.Project;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Date;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class SourcePublisherTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  private SourcePublisher publisher;
+
+  private File sourceFile;
+
+  private BatchReportWriter writer;
+
+  @Before
+  public void prepare() throws IOException {
+    Project p = new Project("foo").setAnalysisDate(new Date(1234567L));
+    ResourceCache resourceCache = new ResourceCache();
+    org.sonar.api.resources.Resource sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php");
+    resourceCache.add(p, null).setSnapshot(new Snapshot().setId(2));
+    File baseDir = temp.newFolder();
+    sourceFile = new File(baseDir, "src/Foo.php");
+    resourceCache.add(sampleFile, null).setInputPath(new DefaultInputFile("foo", "src/Foo.php").setLines(5).setModuleBaseDir(baseDir.toPath()).setCharset(Charsets.ISO_8859_1));
+    publisher = new SourcePublisher(resourceCache);
+    File outputDir = temp.newFolder();
+    writer = new BatchReportWriter(outputDir);
+  }
+
+  @Test
+  public void publishEmptySource() throws Exception {
+    FileUtils.write(sourceFile, "", Charsets.ISO_8859_1);
+
+    publisher.publish(writer);
+
+    File out = writer.getSourceFile(1);
+    assertThat(FileUtils.readFileToString(out, Charsets.UTF_8)).isEqualTo("");
+  }
+
+  @Test
+  public void publishSourceWithLastEmptyLine() throws Exception {
+    FileUtils.write(sourceFile, "1\n2\n3\n4\n", Charsets.ISO_8859_1);
+
+    publisher.publish(writer);
+
+    File out = writer.getSourceFile(1);
+    assertThat(FileUtils.readFileToString(out, Charsets.UTF_8)).isEqualTo("1\n2\n3\n4\n");
+  }
+
+  @Test
+  public void publishSourceWithLastLineNotEmpty() throws Exception {
+    FileUtils.write(sourceFile, "1\n2\n3\n4\n5", Charsets.ISO_8859_1);
+
+    publisher.publish(writer);
+
+    File out = writer.getSourceFile(1);
+    assertThat(FileUtils.readFileToString(out, Charsets.UTF_8)).isEqualTo("1\n2\n3\n4\n5");
+  }
+
+  @Test
+  public void cleanLineEnds() throws Exception {
+    FileUtils.write(sourceFile, "\n2\r\n3\n4\r5", Charsets.ISO_8859_1);
+
+    publisher.publish(writer);
+
+    File out = writer.getSourceFile(1);
+    assertThat(FileUtils.readFileToString(out, Charsets.UTF_8)).isEqualTo("\n2\n3\n4\n5");
+  }
+}
index 40a0cb87d8941b3304acc93144df26e8cf296a44..ea7b38ce9c71453af247ef3affe481ad7a56c106 100644 (file)
@@ -50,18 +50,18 @@ public class FileMetadata implements BatchComponent {
   private static final char LINE_FEED = '\n';
   private static final char CARRIAGE_RETURN = '\r';
 
-  private abstract static class CharHandler {
+  public abstract static class CharHandler {
 
-    void handleAll(char c) {
+    protected void handleAll(char c) {
     }
 
-    void handleIgnoreEoL(char c) {
+    protected void handleIgnoreEoL(char c) {
     }
 
-    void newLine() {
+    protected void newLine() {
     }
 
-    void eof() {
+    protected void eof() {
     }
   }
 
@@ -79,7 +79,7 @@ public class FileMetadata implements BatchComponent {
     }
 
     @Override
-    void handleAll(char c) {
+    protected void handleAll(char c) {
       if (this.lines == 0) {
         this.lines = 1;
       }
@@ -91,7 +91,7 @@ public class FileMetadata implements BatchComponent {
     }
 
     @Override
-    void newLine() {
+    protected void newLine() {
       lines++;
       if (!blankLine) {
         nonBlankLines++;
@@ -100,14 +100,14 @@ public class FileMetadata implements BatchComponent {
     }
 
     @Override
-    void handleIgnoreEoL(char c) {
+    protected void handleIgnoreEoL(char c) {
       if (!Character.isWhitespace(c)) {
         blankLine = false;
       }
     }
 
     @Override
-    void eof() {
+    protected void eof() {
       if (!blankLine) {
         nonBlankLines++;
       }
@@ -128,19 +128,19 @@ public class FileMetadata implements BatchComponent {
     private StringBuilder sb = new StringBuilder();
 
     @Override
-    void handleIgnoreEoL(char c) {
+    protected void handleIgnoreEoL(char c) {
       sb.append(c);
     }
 
     @Override
-    void newLine() {
+    protected void newLine() {
       sb.append(LINE_FEED);
       globalMd5Digest.update(sb.toString().getBytes(Charsets.UTF_8));
       sb.setLength(0);
     }
 
     @Override
-    void eof() {
+    protected void eof() {
       if (sb.length() > 0) {
         globalMd5Digest.update(sb.toString().getBytes(Charsets.UTF_8));
       }
@@ -163,21 +163,21 @@ public class FileMetadata implements BatchComponent {
     }
 
     @Override
-    void handleIgnoreEoL(char c) {
+    protected void handleIgnoreEoL(char c) {
       if (!Character.isWhitespace(c)) {
         sb.append(c);
       }
     }
 
     @Override
-    void newLine() {
+    protected void newLine() {
       consumer.consume(line, sb.length() > 0 ? lineMd5Digest.digest(sb.toString().getBytes(Charsets.UTF_8)) : null);
       sb.setLength(0);
       line++;
     }
 
     @Override
-    void eof() {
+    protected void eof() {
       consumer.consume(line, sb.length() > 0 ? lineMd5Digest.digest(sb.toString().getBytes(Charsets.UTF_8)) : null);
     }
 
@@ -193,17 +193,17 @@ public class FileMetadata implements BatchComponent {
     }
 
     @Override
-    void handleAll(char c) {
+    protected void handleAll(char c) {
       currentOriginalOffset++;
     }
 
     @Override
-    void newLine() {
+    protected void newLine() {
       originalLineOffsets.add(currentOriginalOffset);
     }
 
     @Override
-    void eof() {
+    protected void eof() {
       lastValidOffset = currentOriginalOffset;
     }
 
@@ -246,7 +246,7 @@ public class FileMetadata implements BatchComponent {
       lineOffsetCounter.getLastValidOffset());
   }
 
-  private static void readFile(File file, Charset encoding, CharHandler... handlers) {
+  public static void readFile(File file, Charset encoding, CharHandler... handlers) {
     try (BOMInputStream bomIn = new BOMInputStream(new FileInputStream(file),
       ByteOrderMark.UTF_8, ByteOrderMark.UTF_16LE, ByteOrderMark.UTF_16BE, ByteOrderMark.UTF_32LE, ByteOrderMark.UTF_32BE);
       Reader reader = new BufferedReader(new InputStreamReader(bomIn, encoding))) {