aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java4
-rw-r--r--sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java30
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/SourcePublisher.java68
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java1
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/report/CoveragePublisherTest.java1
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/report/SourcePublisherTest.java104
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java38
7 files changed, 212 insertions, 34 deletions
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java
index 97b7e5f2caa..86ec1c53f6e 100644
--- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java
+++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/BatchReportWriter.java
@@ -118,4 +118,8 @@ public class BatchReportWriter {
ProtobufUtil.writeMessagesToFile(coverageList, file);
}
+ public File getSourceFile(int componentRef) {
+ return fileStructure.fileFor(FileStructure.Domain.SOURCE, componentRef);
+ }
+
}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java
index 21df5a4cafb..e0add6865a0 100644
--- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java
+++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/output/FileStructure.java
@@ -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
index 00000000000..ccb91681e2b
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/SourcePublisher.java
@@ -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);
+ }
+ }
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
index 43ba3500126..12b0bc0f21d 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
@@ -188,6 +188,7 @@ public class ProjectScanContainer extends ComponentContainer {
MeasuresPublisher.class,
DuplicationsPublisher.class,
CoveragePublisher.class,
+ SourcePublisher.class,
ScanTaskObservers.class);
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/CoveragePublisherTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/CoveragePublisherTest.java
index 2e1614bbdf1..347761203f7 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/report/CoveragePublisherTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/report/CoveragePublisherTest.java
@@ -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
index 00000000000..824a6da2db9
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/report/SourcePublisherTest.java
@@ -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");
+ }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java
index 40a0cb87d89..ea7b38ce9c7 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/FileMetadata.java
@@ -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))) {