123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- /*
- * Sonar Runner - API
- * Copyright (C) 2011 SonarSource
- * dev@sonar.codehaus.org
- *
- * 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 02
- */
- package org.sonar.runner;
-
- import org.apache.commons.io.IOUtils;
-
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Locale;
- import java.util.Properties;
-
- /**
- * Arguments :
- * <ul>
- * <li>runner.home: optional path to runner home (root directory with sub-directories bin, lib and conf)</li>
- * <li>runner.settings: optional path to runner global settings, usually ${runner.home}/conf/sonar-runner.properties.
- * This property is used only if ${runner.home} is not defined</li>
- * <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>
- * <li>project.settings: optional path to project settings. Default value is ${project.home}/sonar-project.properties.</li>
- * </ul>
- *
- * @since 1.0
- */
- public final class Main {
-
- private static final String RUNNER_HOME = "runner.home";
- private static final String RUNNER_SETTINGS = "runner.settings";
- private static final String PROJECT_HOME = "project.home";
- private static final String PROJECT_SETTINGS = "project.settings";
- // TODO Remove this after everything is updated to support tasks
- private static final String TASK_COMMAND = "sonar.task";
-
- boolean debugMode = false;
- boolean displayVersionOnly = false;
- boolean displayStackTrace = false;
- String command;
- Properties globalProperties;
- Properties projectProperties;
-
- /**
- * Entry point of the program.
- */
- public static void main(String[] args) {
- new Main().execute(args);
- }
-
- Main() {
- }
-
- private void execute(String[] args) {
- Properties argsProperties = parseArguments(args);
- System.out.println("Runner version: " + Version.getVersion());
- System.out.println("Java version: " + System.getProperty("java.version", "<unknown>")
- + ", vendor: " + System.getProperty("java.vendor", "<unknown>"));
- System.out
- .println("OS name: \"" + System.getProperty("os.name") + "\", version: \"" + System.getProperty("os.version") + "\", arch: \"" + System.getProperty("os.arch") + "\"");
- if (!displayVersionOnly) {
- int result = execute(argsProperties);
- System.exit(result);
- }
- }
-
- private int execute(Properties argsProperties) {
- if (displayStackTrace) {
- Logs.info("Error stacktraces are turned on.");
- }
- Stats stats = new Stats().start();
- try {
- loadProperties(argsProperties);
- Runner runner = Runner.create(command, globalProperties, projectProperties);
- Logs.info("Default locale: \"" + Locale.getDefault() + "\", source code encoding: \"" + runner.getSourceCodeEncoding() + "\""
- + (runner.isEncodingPlatformDependant() ? " (analysis is platform dependent)" : ""));
- Logs.debug("Other system properties:");
- Logs.debug(" - sun.arch.data.model: \"" + System.getProperty("sun.arch.data.model") + "\"");
- Logs.info("Server: " + runner.getSonarServerURL());
- try {
- Logs.info("Work directory: " + runner.getWorkDir().getCanonicalPath());
- Logs.info("Cache directory: " + runner.getCache().getCacheLocation());
- } catch (IOException e) {
- throw new RunnerException("Unable to resolve directory", e);
- }
- runner.execute();
- } catch (Exception e) {
- displayExecutionResult(stats, "FAILURE");
- showError("Error during Sonar runner execution", e, displayStackTrace);
- return 1;
- }
- displayExecutionResult(stats, "SUCCESS");
- return 0;
- }
-
- private void displayExecutionResult(Stats stats, String resultMsg) {
- Logs.info("------------------------------------------------------------------------");
- Logs.info("EXECUTION " + resultMsg);
- Logs.info("------------------------------------------------------------------------");
- stats.stop();
- Logs.info("------------------------------------------------------------------------");
- }
-
- public void showError(String message, Throwable e, boolean showStackTrace) {
- if (showStackTrace) {
- Logs.error(message, e);
- if (!debugMode) {
- Logs.error("");
- suggestDebugMode();
- }
- }
- else {
- Logs.error(message);
- if (e != null) {
- Logs.error(e.getMessage());
- String previousMsg = "";
- for (Throwable cause = e.getCause(); cause != null
- && cause.getMessage() != null
- && !cause.getMessage().equals(previousMsg); cause = cause.getCause()) {
- Logs.error("Caused by: " + cause.getMessage());
- previousMsg = cause.getMessage();
- }
- }
- Logs.error("");
- Logs.error("To see the full stack trace of the errors, re-run Sonar Runner with the -e switch.");
- if (!debugMode) {
- suggestDebugMode();
- }
- }
- }
-
- private void suggestDebugMode() {
- Logs.error("Re-run Sonar Runner using the -X switch to enable full debug logging.");
- }
-
- void loadProperties(Properties argsProperties) {
- globalProperties = loadGlobalProperties(argsProperties);
- projectProperties = loadProjectProperties(argsProperties);
- }
-
- Properties loadGlobalProperties(Properties argsProperties) {
- Properties commandLineProps = new Properties();
- commandLineProps.putAll(System.getProperties());
- commandLineProps.putAll(argsProperties);
-
- Properties result = new Properties();
- result.putAll(loadRunnerConfiguration(commandLineProps));
- result.putAll(commandLineProps);
-
- return result;
- }
-
- Properties loadProjectProperties(Properties argsProperties) {
- Properties commandLineProps = new Properties();
- commandLineProps.putAll(System.getProperties());
- commandLineProps.putAll(argsProperties);
-
- Properties result = new Properties();
- result.putAll(loadProjectConfiguration(commandLineProps));
- result.putAll(commandLineProps);
-
- if (result.containsKey(PROJECT_HOME)) {
- // the real property of the Sonar Runner is "sonar.projectDir"
- String baseDir = result.getProperty(PROJECT_HOME);
- result.remove(PROJECT_HOME);
- result.put(Runner.PROPERTY_SONAR_PROJECT_BASEDIR, baseDir);
- }
-
- return result;
- }
-
- Properties loadRunnerConfiguration(Properties props) {
- File settingsFile = locatePropertiesFile(props, RUNNER_HOME, "conf/sonar-runner.properties", RUNNER_SETTINGS);
- if (settingsFile != null && settingsFile.isFile() && settingsFile.exists()) {
- Logs.info("Runner configuration file: " + settingsFile.getAbsolutePath());
- return toProperties(settingsFile);
- }
- Logs.info("Runner configuration file: NONE");
- return new Properties();
- }
-
- private Properties loadProjectConfiguration(Properties props) {
- File settingsFile = locatePropertiesFile(props, PROJECT_HOME, "sonar-project.properties", PROJECT_SETTINGS);
- if (settingsFile != null && settingsFile.isFile() && settingsFile.exists()) {
- Logs.info("Project configuration file: " + settingsFile.getAbsolutePath());
- return toProperties(settingsFile);
- }
- Logs.info("Project configuration file: NONE");
- return new Properties();
- }
-
- private File locatePropertiesFile(Properties props, String homeKey, String relativePathFromHome, String settingsKey) {
- File settingsFile = null;
- String runnerHome = props.getProperty(homeKey);
- if (runnerHome != null && !"".equals(runnerHome)) {
- settingsFile = new File(runnerHome, relativePathFromHome);
- }
-
- if (settingsFile == null || !settingsFile.exists()) {
- String settingsPath = props.getProperty(settingsKey);
- if (settingsPath != null && !"".equals(settingsPath)) {
- settingsFile = new File(settingsPath);
- }
- }
- return settingsFile;
- }
-
- private Properties toProperties(File file) {
- InputStream in = null;
- Properties properties = new Properties();
- try {
- in = new FileInputStream(file);
- properties.load(in);
- return properties;
-
- } catch (Exception e) {
- throw new IllegalStateException("Fail to load file: " + file.getAbsolutePath(), e);
-
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
- Properties parseArguments(String[] args) {
- int i = 0;
- if (args.length > 0 && !args[0].startsWith("-")) {
- command = args[0];
- i++;
- }
- else {
- command = null;
- }
- Properties props = new Properties();
- for (; i < args.length; i++) {
- String arg = args[i];
- if ("-h".equals(arg) || "--help".equals(arg)) {
- printUsage();
- }
- else if ("-v".equals(arg) || "--version".equals(arg)) {
- displayVersionOnly = true;
- }
- else if ("-e".equals(arg) || "--errors".equals(arg)) {
- displayStackTrace = true;
- }
- else if ("-X".equals(arg) || "--debug".equals(arg)) {
- props.setProperty(Runner.PROPERTY_VERBOSE, "true");
- displayStackTrace = true;
- debugMode = true;
- Logs.setDebugEnabled(true);
- }
- else if ("-D".equals(arg) || "--define".equals(arg)) {
- i++;
- if (i >= args.length) {
- printError("Missing argument for option --define");
- }
- arg = args[i];
- appendPropertyTo(arg, props);
-
- }
- else if (arg.startsWith("-D")) {
- arg = arg.substring(2);
- appendPropertyTo(arg, props);
-
- }
- else {
- printError("Unrecognized option: " + arg);
- }
- }
- return props;
- }
-
- private void appendPropertyTo(String arg, Properties props) {
- final String key, value;
- int j = arg.indexOf('=');
- if (j == -1) {
- key = arg;
- value = "true";
- } else {
- key = arg.substring(0, j);
- value = arg.substring(j + 1);
- }
- if (TASK_COMMAND.equals(key)) {
- command = value;
- }
- else {
- props.setProperty(key, value);
- }
- }
-
- private void printError(String message) {
- Logs.error(message);
- printUsage();
- }
-
- private void printUsage() {
- Logs.info("");
- Logs.info("usage: sonar-runner [command] [options]");
- Logs.info("");
- Logs.info("Command:");
- Logs.info(" analyse-project Run Sonar analysis task on the current project (default)");
- Logs.info(" list-tasks Display all tasks available");
- Logs.info("Options:");
- Logs.info(" -D,--define <arg> Define property");
- Logs.info(" -e,--errors Produce execution error messages");
- Logs.info(" -h,--help Display help information");
- Logs.info(" -v,--version Display version information");
- Logs.info(" -X,--debug Produce execution debug output");
- System.exit(0);
- }
- }
|