@@ -27,6 +27,8 @@ import org.sonar.core.util.CloseableIterator; | |||
public interface BatchReportReader { | |||
BatchReport.Metadata readMetadata(); | |||
CloseableIterator<String> readScannerLogs(); | |||
CloseableIterator<BatchReport.ActiveRule> readActiveRules(); | |||
CloseableIterator<BatchReport.Measure> readComponentMeasures(int componentRef); |
@@ -26,6 +26,7 @@ import com.google.protobuf.Parser; | |||
import java.io.File; | |||
import java.io.FileInputStream; | |||
import java.io.IOException; | |||
import java.io.InputStreamReader; | |||
import java.nio.charset.StandardCharsets; | |||
import java.util.NoSuchElementException; | |||
import javax.annotation.CheckForNull; | |||
@@ -34,6 +35,7 @@ import org.apache.commons.io.IOUtils; | |||
import org.apache.commons.io.LineIterator; | |||
import org.sonar.batch.protocol.output.BatchReport; | |||
import org.sonar.core.util.CloseableIterator; | |||
import org.sonar.core.util.LineReaderIterator; | |||
public class BatchReportReaderImpl implements BatchReportReader { | |||
private final org.sonar.batch.protocol.output.BatchReportReader delegate; | |||
@@ -52,6 +54,20 @@ public class BatchReportReaderImpl implements BatchReportReader { | |||
return this.metadata; | |||
} | |||
@Override | |||
public CloseableIterator<String> readScannerLogs() { | |||
File file = delegate.getFileStructure().analysisLog(); | |||
if (!file.exists()) { | |||
return CloseableIterator.emptyCloseableIterator(); | |||
} | |||
try { | |||
InputStreamReader reader = new InputStreamReader(FileUtils.openInputStream(file), StandardCharsets.UTF_8); | |||
return new LineReaderIterator(reader); | |||
} catch (IOException e) { | |||
throw new IllegalStateException("Fail to open file " + file, e); | |||
} | |||
} | |||
@Override | |||
public CloseableIterator<BatchReport.ActiveRule> readActiveRules() { | |||
return delegate.readActiveRules(); |
@@ -0,0 +1,53 @@ | |||
/* | |||
* 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.server.computation.step; | |||
import org.sonar.api.utils.log.Logger; | |||
import org.sonar.api.utils.log.Loggers; | |||
import org.sonar.core.util.CloseableIterator; | |||
import org.sonar.server.computation.batch.BatchReportReader; | |||
public class LogScannerContextStep implements ComputationStep { | |||
private static final Logger LOGGER = Loggers.get(LogScannerContextStep.class); | |||
private final BatchReportReader reportReader; | |||
public LogScannerContextStep(BatchReportReader reportReader) { | |||
this.reportReader = reportReader; | |||
} | |||
@Override | |||
public void execute() { | |||
CloseableIterator<String> logs = reportReader.readScannerLogs(); | |||
try { | |||
while (logs.hasNext()) { | |||
LOGGER.info(logs.next()); | |||
} | |||
} finally { | |||
logs.close(); | |||
} | |||
} | |||
@Override | |||
public String getDescription() { | |||
return "Log scanner context"; | |||
} | |||
} |
@@ -38,8 +38,8 @@ public class ReportComputationSteps implements ComputationSteps { | |||
@Override | |||
public List<Class<? extends ComputationStep>> orderedStepClasses() { | |||
return Arrays.asList( | |||
// extract report to a temp directory | |||
ExtractReportStep.class, | |||
LogScannerContextStep.class, | |||
// Builds Component tree | |||
BuildComponentTreeStep.class, |
@@ -80,6 +80,21 @@ public class BatchReportReaderImplTest { | |||
assertThat(underTest.readMetadata()).isSameAs(res); | |||
} | |||
@Test | |||
public void readScannerLogs() throws IOException { | |||
File scannerLogFile = writer.getFileStructure().analysisLog(); | |||
FileUtils.write(scannerLogFile, "log1\nlog2"); | |||
CloseableIterator<String> logs = underTest.readScannerLogs(); | |||
assertThat(logs).containsExactly("log1", "log2"); | |||
} | |||
@Test | |||
public void readScannerLogs_no_logs() { | |||
CloseableIterator<String> logs = underTest.readScannerLogs(); | |||
assertThat(logs.hasNext()).isFalse(); | |||
} | |||
@Test | |||
public void readComponentMeasures_returns_empty_list_if_there_is_no_measure() { | |||
assertThat(underTest.readComponentMeasures(COMPONENT_REF)).isEmpty(); |
@@ -36,6 +36,7 @@ import org.sonar.core.util.CloseableIterator; | |||
public class BatchReportReaderRule implements TestRule, BatchReportReader { | |||
private BatchReport.Metadata metadata; | |||
private List<String> scannerLogs; | |||
private List<BatchReport.ActiveRule> activeRules = new ArrayList<>(); | |||
private Map<Integer, List<BatchReport.Measure>> measures = new HashMap<>(); | |||
private Map<Integer, BatchReport.Changesets> changesets = new HashMap<>(); | |||
@@ -65,6 +66,7 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader { | |||
private void clear() { | |||
this.metadata = null; | |||
this.scannerLogs = null; | |||
this.measures.clear(); | |||
this.changesets.clear(); | |||
this.components.clear(); | |||
@@ -90,6 +92,18 @@ public class BatchReportReaderRule implements TestRule, BatchReportReader { | |||
this.metadata = metadata; | |||
} | |||
@Override | |||
public CloseableIterator<String> readScannerLogs() { | |||
if (scannerLogs == null) { | |||
throw new IllegalStateException("Scanner logs are missing"); | |||
} | |||
return CloseableIterator.from(scannerLogs.iterator()); | |||
} | |||
public void setScannerLogs(@Nullable List<String> logs) { | |||
this.scannerLogs = logs; | |||
} | |||
@Override | |||
public CloseableIterator<BatchReport.ActiveRule> readActiveRules() { | |||
if (activeRules == null) { |
@@ -0,0 +1,50 @@ | |||
/* | |||
* 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.server.computation.step; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.sonar.api.utils.log.LogTester; | |||
import org.sonar.api.utils.log.LoggerLevel; | |||
import org.sonar.server.computation.batch.BatchReportReaderRule; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class LogScannerContextStepTest { | |||
@Rule | |||
public BatchReportReaderRule reportReader = new BatchReportReaderRule(); | |||
@Rule | |||
public LogTester logTester = new LogTester(); | |||
LogScannerContextStep underTest = new LogScannerContextStep(reportReader); | |||
@Test | |||
public void log_scanner_logs() { | |||
reportReader.setScannerLogs(asList("log1", "log2")); | |||
underTest.execute(); | |||
assertThat(logTester.logs(LoggerLevel.INFO)).containsExactly("log1", "log2"); | |||
} | |||
} |
@@ -52,7 +52,7 @@ public class ReportComputationStepsTest { | |||
@Test | |||
public void instances_throws_ISE_if_container_does_not_have_second_step() throws Exception { | |||
expectedException.expect(IllegalStateException.class); | |||
expectedException.expectMessage("Component not found: class org.sonar.server.computation.step.BuildComponentTreeStep"); | |||
expectedException.expectMessage("Component not found: class org.sonar.server.computation.step.LogScannerContextStep"); | |||
final ExtractReportStep reportExtractionStep = mock(ExtractReportStep.class); | |||
ComponentContainer componentContainer = new ComponentContainer() { |
@@ -152,4 +152,8 @@ public class BatchReportReader { | |||
private static boolean fileExists(File file) { | |||
return file.exists() && file.isFile(); | |||
} | |||
public FileStructure getFileStructure() { | |||
return fileStructure; | |||
} | |||
} |
@@ -0,0 +1,55 @@ | |||
/* | |||
* 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.core.util; | |||
import java.io.BufferedReader; | |||
import java.io.IOException; | |||
import java.io.Reader; | |||
/** | |||
* Read lines from a {@link Reader} | |||
* @see BufferedReader | |||
*/ | |||
public class LineReaderIterator extends CloseableIterator<String> { | |||
private final BufferedReader reader; | |||
public LineReaderIterator(Reader reader) { | |||
if (reader instanceof BufferedReader) { | |||
this.reader = (BufferedReader) reader; | |||
} else { | |||
this.reader = new BufferedReader(reader); | |||
} | |||
} | |||
@Override | |||
protected String doNext() { | |||
try { | |||
return reader.readLine(); | |||
} catch (IOException e) { | |||
throw new IllegalStateException("Fail to read line", e); | |||
} | |||
} | |||
@Override | |||
protected void doClose() throws IOException { | |||
reader.close(); | |||
} | |||
} |
@@ -0,0 +1,83 @@ | |||
/* | |||
* 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.core.util; | |||
import java.io.BufferedReader; | |||
import java.io.IOException; | |||
import java.io.StringReader; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class LineReaderIteratorTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Test | |||
public void read_lines() { | |||
LineReaderIterator it = new LineReaderIterator(new StringReader("line1\nline2")); | |||
assertThat(it.hasNext()).isTrue(); | |||
assertThat(it.next()).isEqualTo("line1"); | |||
assertThat(it.hasNext()).isTrue(); | |||
assertThat(it.next()).isEqualTo("line2"); | |||
assertThat(it.hasNext()).isFalse(); | |||
} | |||
@Test | |||
public void ignore_last_newline() { | |||
LineReaderIterator it = new LineReaderIterator(new StringReader("line1\nline2\n")); | |||
assertThat(it.hasNext()).isTrue(); | |||
assertThat(it.next()).isEqualTo("line1"); | |||
assertThat(it.hasNext()).isTrue(); | |||
assertThat(it.next()).isEqualTo("line2"); | |||
assertThat(it.hasNext()).isFalse(); | |||
} | |||
@Test | |||
public void no_lines() { | |||
LineReaderIterator it = new LineReaderIterator(new StringReader("")); | |||
assertThat(it.hasNext()).isFalse(); | |||
} | |||
@Test | |||
public void do_not_wrap_BufferedReader_in_BufferedReader() { | |||
// TODO how to verify that constructor does not build new BufferedReader(BufferedReader) ? | |||
LineReaderIterator it = new LineReaderIterator(new BufferedReader(new StringReader("line"))); | |||
assertThat(it.next()).isEqualTo("line"); | |||
assertThat(it.hasNext()).isFalse(); | |||
} | |||
@Test | |||
public void fail_if_cannot_read() throws IOException { | |||
expectedException.expect(IllegalStateException.class); | |||
expectedException.expectMessage("Fail to read line"); | |||
BufferedReader reader = mock(BufferedReader.class); | |||
when(reader.readLine()).thenThrow(new IOException()); | |||
LineReaderIterator it = new LineReaderIterator(reader); | |||
it.hasNext(); | |||
} | |||
} |