3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info 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.ce.task.projectanalysis.batch;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
26 import java.util.NoSuchElementException;
27 import java.util.Optional;
28 import javax.annotation.CheckForNull;
29 import org.apache.commons.io.FileUtils;
30 import org.apache.commons.io.IOUtils;
31 import org.apache.commons.io.LineIterator;
32 import org.sonar.core.util.CloseableIterator;
33 import org.sonar.core.util.LineReaderIterator;
34 import org.sonar.scanner.protocol.output.FileStructure;
35 import org.sonar.scanner.protocol.output.ScannerReport;
36 import org.sonar.scanner.protocol.output.ScannerReport.LineSgnificantCode;
37 import org.sonar.scanner.protocol.output.ScannerReportReader;
39 import static java.nio.charset.StandardCharsets.UTF_8;
41 public class BatchReportReaderImpl implements BatchReportReader {
43 private final BatchReportDirectoryHolder batchReportDirectoryHolder;
44 private ScannerReportReader delegate;
45 // caching of metadata which are read often
46 private ScannerReport.Metadata metadata;
48 public BatchReportReaderImpl(BatchReportDirectoryHolder batchReportDirectoryHolder) {
49 this.batchReportDirectoryHolder = batchReportDirectoryHolder;
52 private void ensureInitialized() {
53 if (this.delegate == null) {
54 FileStructure fileStructure = new FileStructure(batchReportDirectoryHolder.getDirectory());
55 this.delegate = new ScannerReportReader(fileStructure);
60 public ScannerReport.Metadata readMetadata() {
62 if (this.metadata == null) {
63 this.metadata = delegate.readMetadata();
70 public InputStream getAnalysisCache() {
72 return delegate.getAnalysisCache();
76 public CloseableIterator<String> readScannerLogs() {
78 File file = delegate.getFileStructure().analysisLog();
80 return CloseableIterator.emptyCloseableIterator();
83 InputStreamReader reader = new InputStreamReader(FileUtils.openInputStream(file), UTF_8);
84 return new LineReaderIterator(reader);
85 } catch (IOException e) {
86 throw new IllegalStateException("Fail to open file " + file, e);
91 public CloseableIterator<ScannerReport.ActiveRule> readActiveRules() {
93 return delegate.readActiveRules();
97 public CloseableIterator<ScannerReport.AdHocRule> readAdHocRules() {
99 return delegate.readAdHocRules();
103 public CloseableIterator<ScannerReport.Measure> readComponentMeasures(int componentRef) {
105 return delegate.readComponentMeasures(componentRef);
110 public ScannerReport.Changesets readChangesets(int componentRef) {
112 return delegate.readChangesets(componentRef);
116 public ScannerReport.Component readComponent(int componentRef) {
118 return delegate.readComponent(componentRef);
122 public CloseableIterator<ScannerReport.Issue> readComponentIssues(int componentRef) {
124 return delegate.readComponentIssues(componentRef);
128 public CloseableIterator<ScannerReport.ExternalIssue> readComponentExternalIssues(int componentRef) {
130 return delegate.readComponentExternalIssues(componentRef);
134 public CloseableIterator<ScannerReport.Duplication> readComponentDuplications(int componentRef) {
136 return delegate.readComponentDuplications(componentRef);
140 public CloseableIterator<ScannerReport.CpdTextBlock> readCpdTextBlocks(int componentRef) {
142 return delegate.readCpdTextBlocks(componentRef);
146 public CloseableIterator<ScannerReport.Symbol> readComponentSymbols(int componentRef) {
148 return delegate.readComponentSymbols(componentRef);
152 public CloseableIterator<ScannerReport.SyntaxHighlightingRule> readComponentSyntaxHighlighting(int fileRef) {
154 return delegate.readComponentSyntaxHighlighting(fileRef);
158 public CloseableIterator<ScannerReport.LineCoverage> readComponentCoverage(int fileRef) {
160 return delegate.readComponentCoverage(fileRef);
164 public Optional<CloseableIterator<String>> readFileSource(int fileRef) {
166 File file = delegate.readFileSource(fileRef);
168 return Optional.empty();
172 return Optional.of(new CloseableLineIterator(IOUtils.lineIterator(FileUtils.openInputStream(file), UTF_8)));
173 } catch (IOException e) {
174 throw new IllegalStateException("Fail to traverse file: " + file, e);
178 private static class CloseableLineIterator extends CloseableIterator<String> {
179 private final LineIterator lineIterator;
181 public CloseableLineIterator(LineIterator lineIterator) {
182 this.lineIterator = lineIterator;
186 public boolean hasNext() {
187 return lineIterator.hasNext();
191 public String next() {
192 return lineIterator.next();
196 protected String doNext() {
197 // never called anyway
198 throw new NoSuchElementException("Empty closeable Iterator has no element");
202 protected void doClose() throws IOException {
203 lineIterator.close();
208 public CloseableIterator<ScannerReport.ContextProperty> readContextProperties() {
210 return delegate.readContextProperties();
214 public Optional<CloseableIterator<LineSgnificantCode>> readComponentSignificantCode(int fileRef) {
216 return Optional.ofNullable(delegate.readComponentSignificantCode(fileRef));
220 public Optional<ScannerReport.ChangedLines> readComponentChangedLines(int fileRef) {
222 return Optional.ofNullable(delegate.readComponentChangedLines(fileRef));
226 public CloseableIterator<ScannerReport.AnalysisWarning> readAnalysisWarnings() {
228 return delegate.readAnalysisWarnings();