Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * SonarScanner CLI
  3. * Copyright (C) 2011-2024 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  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.
  10. *
  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.
  15. *
  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.
  19. */
  20. package org.sonarsource.scanner.cli;
  21. import ch.qos.logback.classic.Level;
  22. import java.util.Map;
  23. import java.util.Properties;
  24. import org.slf4j.Logger;
  25. import org.slf4j.LoggerFactory;
  26. import org.sonarsource.scanner.lib.ScannerEngineBootstrapper;
  27. import org.sonarsource.scanner.lib.ScannerEngineFacade;
  28. import org.sonarsource.scanner.lib.ScannerProperties;
  29. /**
  30. * Arguments :
  31. * <ul>
  32. * <li>scanner.home: optional path to Scanner home (root directory with sub-directories bin, lib and conf)</li>
  33. * <li>scanner.settings: optional path to runner global settings, usually ${scanner.home}/conf/sonar-scanner.properties.
  34. * This property is used only if ${scanner.home} is not defined</li>
  35. * <li>project.home: path to project root directory. If not set, then it's supposed to be the directory where the runner is executed</li>
  36. * <li>project.settings: optional path to project settings. Default value is ${project.home}/sonar-project.properties.</li>
  37. * </ul>
  38. *
  39. * @since 1.0
  40. */
  41. public class Main {
  42. private static final Logger LOG = LoggerFactory.getLogger(Main.class);
  43. private final Exit exit;
  44. private final Cli cli;
  45. private final Conf conf;
  46. private ScannerEngineBootstrapper scannerEngineBootstrapper;
  47. private final ScannerEngineBootstrapperFactory bootstrapperFactory;
  48. Main(Exit exit, Cli cli, Conf conf, ScannerEngineBootstrapperFactory bootstrapperFactory) {
  49. this.exit = exit;
  50. this.cli = cli;
  51. this.conf = conf;
  52. this.bootstrapperFactory = bootstrapperFactory;
  53. }
  54. public static void main(String[] args) {
  55. Exit exit = new Exit();
  56. Cli cli = new Cli(exit).parse(args);
  57. Main main = new Main(exit, cli, new Conf(cli, System.getenv()), new ScannerEngineBootstrapperFactory());
  58. main.analyze();
  59. }
  60. void analyze() {
  61. Stats stats = new Stats().start();
  62. int status = Exit.INTERNAL_ERROR;
  63. try {
  64. Properties p = conf.properties();
  65. checkSkip(p);
  66. configureLogging(p);
  67. init(p);
  68. try (var engine = scannerEngineBootstrapper.bootstrap()) {
  69. logServerType(engine);
  70. var success = engine.analyze((Map) p);
  71. if (success) {
  72. displayExecutionResult(stats, "SUCCESS");
  73. status = Exit.SUCCESS;
  74. } else {
  75. displayExecutionResult(stats, "FAILURE");
  76. status = Exit.SCANNER_ENGINE_ERROR;
  77. }
  78. }
  79. } catch (Throwable e) {
  80. displayExecutionResult(stats, "FAILURE");
  81. showError(e, cli.isDebugEnabled());
  82. status = isUserError(e) ? Exit.USER_ERROR : Exit.INTERNAL_ERROR;
  83. } finally {
  84. exit.exit(status);
  85. }
  86. }
  87. private static void logServerType(ScannerEngineFacade engine) {
  88. if (engine.isSonarCloud()) {
  89. LOG.info("Communicating with SonarCloud");
  90. } else {
  91. String serverVersion = engine.getServerVersion();
  92. LOG.info("Communicating with SonarQube Server {}", serverVersion);
  93. }
  94. }
  95. private void checkSkip(Properties properties) {
  96. if ("true".equalsIgnoreCase(properties.getProperty(ScannerProperties.SKIP))) {
  97. LOG.info("SonarScanner CLI analysis skipped");
  98. exit.exit(Exit.SUCCESS);
  99. }
  100. }
  101. private void init(Properties p) {
  102. SystemInfo.print();
  103. if (cli.isDisplayVersionOnly()) {
  104. exit.exit(Exit.SUCCESS);
  105. }
  106. scannerEngineBootstrapper = bootstrapperFactory.create(p, cli.getInvokedFrom());
  107. }
  108. private static void configureLogging(Properties props) {
  109. if ("true".equals(props.getProperty("sonar.verbose"))
  110. || "DEBUG".equalsIgnoreCase(props.getProperty("sonar.log.level"))
  111. || "TRACE".equalsIgnoreCase(props.getProperty("sonar.log.level"))) {
  112. var rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
  113. rootLogger.setLevel(Level.DEBUG);
  114. }
  115. }
  116. private static void displayExecutionResult(Stats stats, String resultMsg) {
  117. LOG.info("EXECUTION {}", resultMsg);
  118. stats.stop();
  119. }
  120. private void showError(Throwable e, boolean debug) {
  121. var message = "Error during SonarScanner CLI execution";
  122. if (debug || !isUserError(e)) {
  123. LOG.error(message, e);
  124. } else {
  125. LOG.error(message);
  126. LOG.error(e.getMessage());
  127. String previousMsg = "";
  128. for (Throwable cause = e.getCause(); cause != null
  129. && cause.getMessage() != null
  130. && !cause.getMessage().equals(previousMsg); cause = cause.getCause()) {
  131. LOG.error("Caused by: {}", cause.getMessage());
  132. previousMsg = cause.getMessage();
  133. }
  134. }
  135. if (!cli.isDebugEnabled()) {
  136. LOG.error("");
  137. suggestDebugMode();
  138. }
  139. }
  140. private static boolean isUserError(Throwable e) {
  141. // class not available at compile time (loaded by isolated classloader)
  142. return "org.sonar.api.utils.MessageException".equals(e.getClass().getName());
  143. }
  144. private void suggestDebugMode() {
  145. if (!cli.isEmbedded()) {
  146. LOG.error("Re-run SonarScanner CLI using the -X switch to enable full debug logging.");
  147. }
  148. }
  149. }