diff options
Diffstat (limited to 'sonar-scanner-engine/src')
4 files changed, 89 insertions, 22 deletions
diff --git a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/bootstrap/BootstrapMediumIT.java b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/bootstrap/BootstrapMediumIT.java index 63317e362b9..6cfd6ea5f94 100644 --- a/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/bootstrap/BootstrapMediumIT.java +++ b/sonar-scanner-engine/src/it/java/org/sonar/scanner/mediumtest/bootstrap/BootstrapMediumIT.java @@ -117,7 +117,7 @@ class BootstrapMediumIT { void should_fail_if_invalid_json_input() { var in = new ByteArrayInputStream("}".getBytes()); - var exitCode = ScannerMain.run(in); + var exitCode = ScannerMain.run(in, System.out); assertThat(exitCode).isEqualTo(1); assertThat(logTester.getLogs(Level.ERROR)).hasSize(1); @@ -128,7 +128,7 @@ class BootstrapMediumIT { @Test void should_warn_if_null_property_key() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{"value": "aValueWithoutKey"}]}""".getBytes())); + {"scannerProperties": [{"value": "aValueWithoutKey"}]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Ignoring property with null key. Value='aValueWithoutKey'"); } @@ -136,7 +136,7 @@ class BootstrapMediumIT { @Test void should_warn_if_null_property_value() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{"key": "aKey", "value": null}]}""".getBytes())); + {"scannerProperties": [{"key": "aKey", "value": null}]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Ignoring property with null value. Key='aKey'"); } @@ -144,7 +144,7 @@ class BootstrapMediumIT { @Test void should_warn_if_not_provided_property_value() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{"key": "aKey"}]}""".getBytes())); + {"scannerProperties": [{"key": "aKey"}]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Ignoring property with null value. Key='aKey'"); } @@ -152,7 +152,7 @@ class BootstrapMediumIT { @Test void should_warn_if_duplicate_property_keys() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{"key": "aKey", "value": "aValue"}, {"key": "aKey", "value": "aValue"}]}""".getBytes())); + {"scannerProperties": [{"key": "aKey", "value": "aValue"}, {"key": "aKey", "value": "aValue"}]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Duplicated properties. Key='aKey'"); } @@ -160,7 +160,7 @@ class BootstrapMediumIT { @Test void should_warn_if_null_property() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{"key": "aKey", "value": "aValue"},]}""".getBytes())); + {"scannerProperties": [{"key": "aKey", "value": "aValue"},]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Ignoring null or empty property"); } @@ -168,7 +168,7 @@ class BootstrapMediumIT { @Test void should_warn_if_empty_property() { ScannerMain.run(new ByteArrayInputStream(""" - {"scannerProperties": [{}]}""".getBytes())); + {"scannerProperties": [{}]}""".getBytes()), System.out); assertThat(logTester.logs(Level.WARN)).contains("Ignoring null or empty property"); } @@ -229,7 +229,7 @@ class BootstrapMediumIT { } private int runScannerEngine(ScannerProperties scannerProperties) { - return ScannerMain.run(new ByteArrayInputStream(scannerProperties.toJson().getBytes())); + return ScannerMain.run(new ByteArrayInputStream(scannerProperties.toJson().getBytes()), System.out); } static class ScannerProperties { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/JGitCleanupService.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/JGitCleanupService.java new file mode 100644 index 00000000000..28e052cfa4e --- /dev/null +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/JGitCleanupService.java @@ -0,0 +1,47 @@ +/* + * SonarQube + * Copyright (C) 2009-2025 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program 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. + * + * This program 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.scanner.bootstrap; + +import java.lang.reflect.Method; +import org.eclipse.jgit.internal.util.CleanupService; + +/** + * Normally, JGit terminates with a shutdown hook. Since we also want to support running the Scanner Engine in the same JVM, this allows triggering shutdown manually. + */ +class JGitCleanupService implements AutoCloseable { + + private final Method shutDownMethod; + private final CleanupService cleanupService; + + public JGitCleanupService() { + cleanupService = new CleanupService(); + try { + shutDownMethod = CleanupService.class.getDeclaredMethod("shutDown"); + } catch (NoSuchMethodException e) { + throw new IllegalStateException("Unable to find method 'shutDown' on JGit CleanupService", e); + } + shutDownMethod.setAccessible(true); + } + + @Override + public void close() throws Exception { + shutDownMethod.invoke(cleanupService); + } +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerMain.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerMain.java index 7e27a45e4cf..bd8d5b9b99c 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerMain.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/ScannerMain.java @@ -21,11 +21,14 @@ package org.sonar.scanner.bootstrap; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.spi.ILoggingEvent; +import ch.qos.logback.core.OutputStreamAppender; import com.google.gson.Gson; import com.google.gson.annotations.SerializedName; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.List; @@ -50,11 +53,13 @@ public class ScannerMain { private static final String SCANNER_APP_VERSION_KEY = "sonar.scanner.appVersion"; public static void main(String... args) { - System.exit(run(System.in)); + System.exit(run(System.in, System.out)); } - public static int run(InputStream in) { - try { + public static int run(InputStream in, OutputStream out) { + try (var ignored = new JGitCleanupService()) { + configureLogOutput(out); + LOG.info("Starting SonarScanner Engine..."); LOG.atInfo().log(ScannerMain::java); @@ -71,6 +76,8 @@ public class ScannerMain { } catch (Throwable throwable) { handleException(throwable); return 1; + } finally { + stopLogback(); } } @@ -156,6 +163,28 @@ public class ScannerMain { rootLogger.setLevel(Level.toLevel(verbose ? LEVEL_ROOT_VERBOSE : LEVEL_ROOT_DEFAULT)); } + private static void configureLogOutput(OutputStream out) { + var loggerContext = (ch.qos.logback.classic.LoggerContext) LoggerFactory.getILoggerFactory(); + var encoder = new ScannerLogbackEncoder(); + encoder.setContext(loggerContext); + encoder.start(); + + var appender = new OutputStreamAppender<ILoggingEvent>(); + appender.setEncoder(encoder); + appender.setContext(loggerContext); + appender.setOutputStream(out); + appender.start(); + + var rootLogger = (Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME); + rootLogger.addAppender(appender); + rootLogger.setLevel(Level.toLevel(LEVEL_ROOT_DEFAULT)); + } + + private static void stopLogback() { + var loggerContext = (ch.qos.logback.classic.LoggerContext) LoggerFactory.getILoggerFactory(); + loggerContext.stop(); + } + private static class Input { @SerializedName("scannerProperties") private List<ScannerProperty> scannerProperties; diff --git a/sonar-scanner-engine/src/main/resources/logback.xml b/sonar-scanner-engine/src/main/resources/logback.xml index ccd0dfe09b9..ddc2805f08a 100644 --- a/sonar-scanner-engine/src/main/resources/logback.xml +++ b/sonar-scanner-engine/src/main/resources/logback.xml @@ -1,17 +1,8 @@ <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration> -<!-- This logback configuration is used when the scanner engine is bootstrapped using the SonarScannerCli class. --> +<!-- This logback configuration is used when the scanner engine is bootstrapped using the ScannerMain class. --> <configuration scan="false"> - <import class="ch.qos.logback.core.ConsoleAppender"/> - - <appender name="STDOUT" class="ConsoleAppender"> - <encoder class="org.sonar.scanner.bootstrap.ScannerLogbackEncoder"/> - </appender> - - <root level="info"> - <appender-ref ref="STDOUT"/> - </root> <!-- BeanUtils generate too many DEBUG logs when sonar.verbose is set --> <logger name="org.apache.commons.beanutils.converters" level="WARN"/> @@ -31,4 +22,4 @@ <logger name="nl.altindag.ssl.util.CertificateUtils" level="INFO"/> -</configuration>
\ No newline at end of file +</configuration> |