You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Main.java 5.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * SonarScanner CLI
  3. * Copyright (C) 2011-2022 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 java.util.Locale;
  22. import java.util.Map;
  23. import java.util.Properties;
  24. import org.sonarsource.scanner.api.EmbeddedScanner;
  25. import org.sonarsource.scanner.api.ScanProperties;
  26. /**
  27. * Arguments :
  28. * <ul>
  29. * <li>scanner.home: optional path to Scanner home (root directory with sub-directories bin, lib and conf)</li>
  30. * <li>scanner.settings: optional path to runner global settings, usually ${scanner.home}/conf/sonar-scanner.properties.
  31. * This property is used only if ${scanner.home} is not defined</li>
  32. * <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>
  33. * <li>project.settings: optional path to project settings. Default value is ${project.home}/sonar-project.properties.</li>
  34. * </ul>
  35. *
  36. * @since 1.0
  37. */
  38. public class Main {
  39. private static final String SEPARATOR = "------------------------------------------------------------------------";
  40. private final Exit exit;
  41. private final Cli cli;
  42. private final Conf conf;
  43. private EmbeddedScanner embeddedScanner;
  44. private final ScannerFactory runnerFactory;
  45. private final Logs logger;
  46. Main(Exit exit, Cli cli, Conf conf, ScannerFactory runnerFactory, Logs logger) {
  47. this.exit = exit;
  48. this.cli = cli;
  49. this.conf = conf;
  50. this.runnerFactory = runnerFactory;
  51. this.logger = logger;
  52. }
  53. public static void main(String[] args) {
  54. Logs logs = new Logs(System.out, System.err);
  55. Exit exit = new Exit();
  56. Cli cli = new Cli(exit, logs).parse(args);
  57. Main main = new Main(exit, cli, new Conf(cli, logs, System.getenv()), new ScannerFactory(logs), logs);
  58. main.execute();
  59. }
  60. void execute() {
  61. Stats stats = new Stats(logger).start();
  62. int status = Exit.INTERNAL_ERROR;
  63. try {
  64. Properties p = conf.properties();
  65. checkSkip(p);
  66. configureLogging(p);
  67. init(p);
  68. embeddedScanner.start();
  69. if (isSonarCloud(p)) {
  70. logger.info("Analyzing on SonarCloud");
  71. } else {
  72. String serverVersion = embeddedScanner.serverVersion();
  73. logger.info(String.format("Analyzing on SonarQube server %s", serverVersion));
  74. }
  75. execute(stats, p);
  76. status = Exit.SUCCESS;
  77. } catch (Throwable e) {
  78. displayExecutionResult(stats, "FAILURE");
  79. showError("Error during SonarScanner execution", e, cli.isDebugEnabled());
  80. status = isUserError(e) ? Exit.USER_ERROR : Exit.INTERNAL_ERROR;
  81. } finally {
  82. exit.exit(status);
  83. }
  84. }
  85. static boolean isSonarCloud(Properties props) {
  86. String hostUrl = props.getProperty(Conf.PROPERTY_SONAR_HOST_URL);
  87. if (hostUrl != null) {
  88. return hostUrl.toLowerCase(Locale.ENGLISH).contains("sonarcloud");
  89. }
  90. return false;
  91. }
  92. private void checkSkip(Properties properties) {
  93. if ("true".equalsIgnoreCase(properties.getProperty(ScanProperties.SKIP))) {
  94. logger.info("SonarScanner analysis skipped");
  95. exit.exit(Exit.SUCCESS);
  96. }
  97. }
  98. private void init(Properties p) {
  99. SystemInfo.print(logger);
  100. if (cli.isDisplayVersionOnly()) {
  101. exit.exit(Exit.SUCCESS);
  102. }
  103. embeddedScanner = runnerFactory.create(p, cli.getInvokedFrom());
  104. }
  105. private void configureLogging(Properties props) {
  106. if ("true".equals(props.getProperty("sonar.verbose"))
  107. || "DEBUG".equalsIgnoreCase(props.getProperty("sonar.log.level"))
  108. || "TRACE".equalsIgnoreCase(props.getProperty("sonar.log.level"))) {
  109. logger.setDebugEnabled(true);
  110. }
  111. }
  112. private void execute(Stats stats, Properties p) {
  113. embeddedScanner.execute((Map) p);
  114. displayExecutionResult(stats, "SUCCESS");
  115. }
  116. private void displayExecutionResult(Stats stats, String resultMsg) {
  117. logger.info(SEPARATOR);
  118. logger.info("EXECUTION " + resultMsg);
  119. logger.info(SEPARATOR);
  120. stats.stop();
  121. logger.info(SEPARATOR);
  122. }
  123. private void showError(String message, Throwable e, boolean debug) {
  124. if (debug || !isUserError(e)) {
  125. logger.error(message, e);
  126. } else {
  127. logger.error(message);
  128. logger.error(e.getMessage());
  129. String previousMsg = "";
  130. for (Throwable cause = e.getCause(); cause != null
  131. && cause.getMessage() != null
  132. && !cause.getMessage().equals(previousMsg); cause = cause.getCause()) {
  133. logger.error("Caused by: " + cause.getMessage());
  134. previousMsg = cause.getMessage();
  135. }
  136. }
  137. if (!cli.isDebugEnabled()) {
  138. logger.error("");
  139. suggestDebugMode();
  140. }
  141. }
  142. private static boolean isUserError(Throwable e) {
  143. // class not available at compile time (loaded by isolated classloader)
  144. return "org.sonar.api.utils.MessageException".equals(e.getClass().getName());
  145. }
  146. private void suggestDebugMode() {
  147. if (!cli.isEmbedded()) {
  148. logger.error("Re-run SonarScanner using the -X switch to enable full debug logging.");
  149. }
  150. }
  151. }