3 * Copyright (C) 2009-2016 SonarSource SA
4 * mailto:contact AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.computation.task.projectanalysis.batch;
22 import com.google.common.base.Optional;
23 import com.google.common.base.Throwables;
24 import com.google.protobuf.InvalidProtocolBufferException;
25 import com.google.protobuf.Parser;
27 import java.io.FileInputStream;
28 import java.io.IOException;
29 import java.io.InputStreamReader;
30 import java.nio.charset.StandardCharsets;
31 import java.util.NoSuchElementException;
32 import javax.annotation.CheckForNull;
33 import org.apache.commons.io.FileUtils;
34 import org.apache.commons.io.IOUtils;
35 import org.apache.commons.io.LineIterator;
36 import org.sonar.core.util.CloseableIterator;
37 import org.sonar.core.util.LineReaderIterator;
38 import org.sonar.scanner.protocol.output.ScannerReport;
40 public class BatchReportReaderImpl implements BatchReportReader {
41 private final org.sonar.scanner.protocol.output.ScannerReportReader delegate;
42 // caching of metadata which are read often
43 private ScannerReport.Metadata metadata;
45 public BatchReportReaderImpl(BatchReportDirectoryHolder batchReportDirectoryHolder) {
46 this.delegate = new org.sonar.scanner.protocol.output.ScannerReportReader(batchReportDirectoryHolder.getDirectory());
50 public ScannerReport.Metadata readMetadata() {
51 if (this.metadata == null) {
52 this.metadata = delegate.readMetadata();
58 public CloseableIterator<String> readScannerLogs() {
59 File file = delegate.getFileStructure().analysisLog();
61 return CloseableIterator.emptyCloseableIterator();
64 InputStreamReader reader = new InputStreamReader(FileUtils.openInputStream(file), StandardCharsets.UTF_8);
65 return new LineReaderIterator(reader);
66 } catch (IOException e) {
67 throw new IllegalStateException("Fail to open file " + file, e);
72 public CloseableIterator<ScannerReport.ActiveRule> readActiveRules() {
73 return delegate.readActiveRules();
77 public CloseableIterator<ScannerReport.Measure> readComponentMeasures(int componentRef) {
78 return delegate.readComponentMeasures(componentRef);
83 public ScannerReport.Changesets readChangesets(int componentRef) {
84 return delegate.readChangesets(componentRef);
88 public ScannerReport.Component readComponent(int componentRef) {
89 return delegate.readComponent(componentRef);
93 public CloseableIterator<ScannerReport.Issue> readComponentIssues(int componentRef) {
94 return delegate.readComponentIssues(componentRef);
98 public CloseableIterator<ScannerReport.Duplication> readComponentDuplications(int componentRef) {
99 return delegate.readComponentDuplications(componentRef);
103 public CloseableIterator<ScannerReport.CpdTextBlock> readCpdTextBlocks(int componentRef) {
104 return delegate.readCpdTextBlocks(componentRef);
108 public CloseableIterator<ScannerReport.Symbol> readComponentSymbols(int componentRef) {
109 return delegate.readComponentSymbols(componentRef);
113 public CloseableIterator<ScannerReport.SyntaxHighlightingRule> readComponentSyntaxHighlighting(int fileRef) {
114 return delegate.readComponentSyntaxHighlighting(fileRef);
118 public CloseableIterator<ScannerReport.LineCoverage> readComponentCoverage(int fileRef) {
119 return delegate.readComponentCoverage(fileRef);
123 public Optional<CloseableIterator<String>> readFileSource(int fileRef) {
124 File file = delegate.readFileSource(fileRef);
126 return Optional.absent();
130 return Optional.<CloseableIterator<String>>of(new CloseableLineIterator(IOUtils.lineIterator(FileUtils.openInputStream(file), StandardCharsets.UTF_8)));
131 } catch (IOException e) {
132 throw new IllegalStateException("Fail to traverse file: " + file, e);
136 private static class CloseableLineIterator extends CloseableIterator<String> {
137 private final LineIterator lineIterator;
139 public CloseableLineIterator(LineIterator lineIterator) {
140 this.lineIterator = lineIterator;
144 public boolean hasNext() {
145 return lineIterator.hasNext();
149 public String next() {
150 return lineIterator.next();
154 protected String doNext() {
155 // never called anyway
156 throw new NoSuchElementException("Empty closeable Iterator has no element");
160 protected void doClose() throws Exception {
161 lineIterator.close();
166 public CloseableIterator<ScannerReport.Test> readTests(int testFileRef) {
167 File file = delegate.readTests(testFileRef);
169 return CloseableIterator.emptyCloseableIterator();
173 return new ParserCloseableIterator<>(ScannerReport.Test.parser(), FileUtils.openInputStream(file));
174 } catch (IOException e) {
175 Throwables.propagate(e);
176 // actually never reached
177 return CloseableIterator.emptyCloseableIterator();
182 public CloseableIterator<ScannerReport.CoverageDetail> readCoverageDetails(int testFileRef) {
183 File file = delegate.readCoverageDetails(testFileRef);
185 return CloseableIterator.emptyCloseableIterator();
189 return new ParserCloseableIterator<>(ScannerReport.CoverageDetail.parser(), FileUtils.openInputStream(file));
190 } catch (IOException e) {
191 Throwables.propagate(e);
192 // actually never reached
193 return CloseableIterator.emptyCloseableIterator();
197 private static class ParserCloseableIterator<T> extends CloseableIterator<T> {
198 private final Parser<T> parser;
199 private final FileInputStream fileInputStream;
201 public ParserCloseableIterator(Parser<T> parser, FileInputStream fileInputStream) {
202 this.parser = parser;
203 this.fileInputStream = fileInputStream;
207 protected T doNext() {
209 return parser.parseDelimitedFrom(fileInputStream);
210 } catch (InvalidProtocolBufferException e) {
211 Throwables.propagate(e);
212 // actually never reached
218 protected void doClose() throws Exception {
219 fileInputStream.close();