diff options
Diffstat (limited to 'sonar-runner-api')
42 files changed, 1079 insertions, 2201 deletions
diff --git a/sonar-runner-api/pom.xml b/sonar-runner-api/pom.xml index af33a64..9a7208f 100644 --- a/sonar-runner-api/pom.xml +++ b/sonar-runner-api/pom.xml @@ -1,48 +1,48 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.codehaus.sonar.runner</groupId> <artifactId>sonar-runner</artifactId> - <version>2.1-SNAPSHOT</version> + <version>2.2-SNAPSHOT</version> </parent> <artifactId>sonar-runner-api</artifactId> <name>Sonar Runner - API</name> <dependencies> - <!-- Dependencies will be shaded --> + <!-- Dependencies with scope "compile" are shaded and removed from transitive dependencies--> <dependency> - <groupId>commons-io</groupId> - <artifactId>commons-io</artifactId> - <version>2.2</version> + <groupId>${pom.groupId}</groupId> + <artifactId>sonar-runner-impl</artifactId> + <version>${pom.version}</version> </dependency> <dependency> - <groupId>commons-codec</groupId> - <artifactId>commons-codec</artifactId> - <version>1.4</version> + <groupId>com.google.code.findbugs</groupId> + <artifactId>jsr305</artifactId> + <scope>provided</scope> </dependency> + + <!-- Unit tests --> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> - <version>2.4</version> + <version>2.6</version> + <scope>test</scope> </dependency> - <!-- Unit tests --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> - <version>4.10</version> <scope>test</scope> </dependency> <dependency> <groupId>org.easytesting</groupId> <artifactId>fest-assert</artifactId> - <version>1.4</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> - <version>1.9.5</version> <scope>test</scope> </dependency> </dependencies> @@ -54,7 +54,6 @@ <filtering>true</filtering> </resource> </resources> - <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> @@ -69,6 +68,34 @@ </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy</id> + <phase>process-resources</phase> + <goals> + <goal>copy</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>${pom.groupId}</groupId> + <artifactId>sonar-runner-impl</artifactId> + <version>${pom.version}</version> + <type>jar</type> + <overWrite>false</overWrite> + <outputDirectory>${project.build.outputDirectory}</outputDirectory> + <destFileName>sonar-runner-impl.jar</destFileName> + </artifactItem> + </artifactItems> + <overWriteReleases>true</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <executions> <execution> @@ -81,14 +108,6 @@ <minimizeJar>true</minimizeJar> <relocations> <relocation> - <pattern>org.apache.commons.io</pattern> - <shadedPattern>org.sonar.runner.commonsio</shadedPattern> - </relocation> - <relocation> - <pattern>org.apache.commons.codec</pattern> - <shadedPattern>org.sonar.runner.commonscodec</shadedPattern> - </relocation> - <relocation> <pattern>org.apache.commons.lang</pattern> <shadedPattern>org.sonar.runner.commonslang</shadedPattern> </relocation> diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/BootstrapClassLoader.java b/sonar-runner-api/src/main/java/org/sonar/runner/BootstrapClassLoader.java deleted file mode 100644 index 75d2a10..0000000 --- a/sonar-runner-api/src/main/java/org/sonar/runner/BootstrapClassLoader.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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 java.io.IOException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Enumeration; - -/** - * Special {@link URLClassLoader} to execute Sonar, which restricts loading from parent. - */ -class BootstrapClassLoader extends URLClassLoader { - - private final String[] unmaskedPackages; - - BootstrapClassLoader(ClassLoader parent, String... unmaskedPackages) { - super(new URL[0], parent); - this.unmaskedPackages = unmaskedPackages; - } - - /** - * {@inheritDoc} Visibility of a method has been relaxed to public. - */ - @Override - public void addURL(URL url) { - super.addURL(url); - } - - /** - * {@inheritDoc} Visibility of a method has been relaxed to public. - */ - @Override - public Class<?> findClass(String name) throws ClassNotFoundException { - return super.findClass(name); - } - - /** - * @return true, if class can be loaded from parent ClassLoader - */ - boolean canLoadFromParent(String name) { - if (name.startsWith("org.sonar.runner.") && !name.startsWith("org.sonar.runner.internal.batch.")) { - return true; - } - for (String pkg : unmaskedPackages) { - if (name.startsWith(pkg + ".")) { - return true; - } - } - return false; - } - - /** - * Same behavior as in {@link URLClassLoader#loadClass(String, boolean)}, except loading from parent. - */ - @Override - protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { - // First, check if the class has already been loaded - Class<?> c = findLoadedClass(name); - if (c == null) { - try { - // Load from parent - if (getParent() != null && canLoadFromParent(name)) { - c = getParent().loadClass(name); - } else { - // Load from system - - // I don't know for other vendors, but for Oracle JVM : - // - ClassLoader.getSystemClassLoader() is sun.misc.Launcher$AppClassLoader. It contains app classpath. - // - ClassLoader.getSystemClassLoader().getParent() is sun.misc.Launcher$ExtClassLoader. It contains core JVM - ClassLoader systemClassLoader = getSystemClassLoader(); - if (systemClassLoader.getParent() != null) { - systemClassLoader = systemClassLoader.getParent(); - } - c = systemClassLoader.loadClass(name); - } - } catch (ClassNotFoundException e) { - // If still not found, then invoke findClass in order - // to find the class. - c = findClass(name); - } - } - if (resolve) { - resolveClass(c); - } - return c; - } - - /** - * Unlike {@link URLClassLoader#getResource(String)} don't return resource from parent. - * See http://jira.codehaus.org/browse/SONAR-2276 - */ - @Override - public URL getResource(String name) { - return findResource(name); - } - - /** - * Unlike {@link URLClassLoader#getResources(String)} don't return resources from parent. - * See http://jira.codehaus.org/browse/SONAR-2276 - */ - @Override - public Enumeration<URL> getResources(String name) throws IOException { - return findResources(name); - } - -} diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/Bootstrapper.java b/sonar-runner-api/src/main/java/org/sonar/runner/Bootstrapper.java deleted file mode 100644 index 64e9694..0000000 --- a/sonar-runner-api/src/main/java/org/sonar/runner/Bootstrapper.java +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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.FileUtils; -import org.apache.commons.io.IOUtils; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.ConnectException; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Bootstrapper used to download everything from the server and create the correct classloader required to execute a Sonar analysis in isolation. - */ -class Bootstrapper { - - static final String VERSION_PATH = "/api/server/version"; - static final String BATCH_PATH = "/batch/"; - static final String BOOTSTRAP_INDEX_PATH = "/batch_bootstrap/index"; - static final int CONNECT_TIMEOUT_MILLISECONDS = 30000; - static final int READ_TIMEOUT_MILLISECONDS = 60000; - private static final Pattern CHARSET_PATTERN = Pattern.compile("(?i)\\bcharset=\\s*\"?([^\\s;\"]*)"); - - private static final String[] UNSUPPORTED_VERSIONS_FOR_CACHE = {"1", "2", "3.0", "3.1", "3.2", "3.3", "3.4"}; - - private File bootDir; - private String serverUrl; - private String productToken; - private String serverVersion; - private SonarCache cache; - - /** - * @param productToken part of User-Agent request-header field - see http://tools.ietf.org/html/rfc1945#section-10.15 - */ - Bootstrapper(String productToken, String serverUrl, File workDir, SonarCache cache) { - this.productToken = productToken; - this.cache = cache; - bootDir = new File(workDir, "batch"); - bootDir.mkdirs(); - if (serverUrl.endsWith("/")) { - this.serverUrl = serverUrl.substring(0, serverUrl.length() - 1); - } else { - this.serverUrl = serverUrl; - } - } - - /** - * @return server url - */ - String getServerUrl() { - return serverUrl; - } - - /** - * @return server version - */ - String getServerVersion() { - if (serverVersion == null) { - try { - serverVersion = remoteContent(VERSION_PATH); - } catch (ConnectException e) { - Logs.error("Sonar server '" + serverUrl + "' can not be reached"); - throw new RunnerException("Fail to request server version", e); - } catch (UnknownHostException e) { - Logs.error("Sonar server '" + serverUrl + "' can not be reached"); - throw new RunnerException("Fail to request server version", e); - } catch (IOException e) { - throw new RunnerException("Fail to request server version", e); - } - } - return serverVersion; - } - - /** - * Download batch files from server and creates {@link BootstrapClassLoader}. - * To use this method version of Sonar should be at least 2.6. - * - * @param urls additional URLs for loading classes and resources - * @param parent parent ClassLoader - * @param unmaskedPackages only classes and resources from those packages would be available for loading from parent - */ - BootstrapClassLoader createClassLoader(URL[] urls, ClassLoader parent, String... unmaskedPackages) { - BootstrapClassLoader classLoader = new BootstrapClassLoader(parent, unmaskedPackages); - List<File> files = downloadBatchFiles(); - for (URL url : urls) { - classLoader.addURL(url); - } - for (File file : files) { - try { - classLoader.addURL(file.toURI().toURL()); - } catch (MalformedURLException e) { - throw new IllegalStateException("Fail to create classloader", e); - } - } - return classLoader; - } - - private void remoteContentToFile(String path, File toFile) { - InputStream input = null; - FileOutputStream output = null; - String fullUrl = serverUrl + path; - if (Logs.isDebugEnabled()) { - Logs.debug("Downloading " + fullUrl + " to " + toFile.getAbsolutePath()); - } - // Don't log for old versions without cache to not pollute logs - else if (!isUnsupportedVersionForCache(getServerVersion())) { - Logs.info("Downloading " + path.substring(path.lastIndexOf("/") + 1)); - } - try { - HttpURLConnection connection = newHttpConnection(new URL(fullUrl)); - output = new FileOutputStream(toFile, false); - input = connection.getInputStream(); - IOUtils.copyLarge(input, output); - } catch (IOException e) { - IOUtils.closeQuietly(output); - FileUtils.deleteQuietly(toFile); - throw new IllegalStateException("Fail to download the file: " + fullUrl, e); - } finally { - IOUtils.closeQuietly(input); - IOUtils.closeQuietly(output); - } - } - - String remoteContent(String path) throws IOException { - String fullUrl = serverUrl + path; - HttpURLConnection conn = newHttpConnection(new URL(fullUrl)); - String charset = getCharsetFromContentType(conn.getContentType()); - if (charset == null || "".equals(charset)) { - charset = "UTF-8"; - } - Reader reader = new InputStreamReader(conn.getInputStream(), charset); - try { - int statusCode = conn.getResponseCode(); - if (statusCode != HttpURLConnection.HTTP_OK) { - throw new IOException("Status returned by url : '" + fullUrl + "' is invalid : " + statusCode); - } - return IOUtils.toString(reader); - } finally { - IOUtils.closeQuietly(reader); - conn.disconnect(); - } - } - - /** - * By convention, the product tokens are listed in order of their significance for identifying the application. - */ - String getUserAgent() { - return "sonar-bootstrapper/" + Version.getVersion() + " " + productToken; - } - - HttpURLConnection newHttpConnection(URL url) throws IOException { - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - connection.setConnectTimeout(CONNECT_TIMEOUT_MILLISECONDS); - connection.setReadTimeout(READ_TIMEOUT_MILLISECONDS); - connection.setInstanceFollowRedirects(true); - connection.setRequestMethod("GET"); - connection.setRequestProperty("User-Agent", getUserAgent()); - return connection; - } - - private List<File> downloadBatchFiles() { - try { - List<File> files = new ArrayList<File>(); - if (isUnsupportedVersionForCache(getServerVersion())) { - getBootstrapFilesFromOldURL(files); - } - else { - getBootstrapFiles(files); - } - return files; - } catch (Exception e) { - throw new IllegalStateException("Fail to download libraries from server", e); - } - } - - private void getBootstrapFilesFromOldURL(List<File> files) throws IOException { - String libs = remoteContent(BATCH_PATH); - for (String lib : libs.split(",")) { - File file = new File(bootDir, lib); - remoteContentToFile(BATCH_PATH + lib, file); - files.add(file); - } - } - - private void getBootstrapFiles(List<File> files) throws IOException { - String libs = remoteContent(BOOTSTRAP_INDEX_PATH); - String[] lines = libs.split("[\r\n]+"); - for (String line : lines) { - line = line.trim(); - if ("".equals(line)) { - continue; - } - String[] libAndMd5 = line.split("\\|"); - String libName = libAndMd5[0]; - String remoteMd5 = libAndMd5.length > 0 ? libAndMd5[1] : null; - File libInCache = null; - if (remoteMd5 != null && !"".equals(remoteMd5)) { - libInCache = cache.getFileFromCache(libName, remoteMd5); - } - if (libInCache == null) { - File tmpLocation = cache.getTemporaryFile(); - remoteContentToFile(BATCH_PATH + libName, tmpLocation); - String md5 = cache.cacheFile(tmpLocation, libName); - libInCache = cache.getFileFromCache(libName, md5); - if (!md5.equals(remoteMd5)) { - throw new RunnerException("INVALID CHECKSUM: File " + libInCache.getAbsolutePath() + " was expected to have checksum " + remoteMd5 - + " but was downloaded with checksum " + md5); - } - } - files.add(libInCache); - } - } - - static boolean isUnsupportedVersionForCache(String version) { - return VersionUtils.isUnsupportedVersion(version, UNSUPPORTED_VERSIONS_FOR_CACHE); - } - - /** - * Parse out a charset from a content type header. - * - * @param contentType e.g. "text/html; charset=EUC-JP" - * @return "EUC-JP", or null if not found. Charset is trimmed and uppercased. - */ - static String getCharsetFromContentType(String contentType) { - if (contentType == null) { - return null; - } - - Matcher m = CHARSET_PATTERN.matcher(contentType); - if (m.find()) { - return m.group(1).trim().toUpperCase(); - } - return null; - } -} diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/Main.java b/sonar-runner-api/src/main/java/org/sonar/runner/Main.java deleted file mode 100644 index a9a653a..0000000 --- a/sonar-runner-api/src/main/java/org/sonar/runner/Main.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * 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); - } -} diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/Runner.java b/sonar-runner-api/src/main/java/org/sonar/runner/Runner.java deleted file mode 100644 index 5b1a436..0000000 --- a/sonar-runner-api/src/main/java/org/sonar/runner/Runner.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * 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.FileUtils; -import org.apache.commons.lang.StringUtils; - -import java.io.File; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; - -/** - * <p> - * Sonar Runner class that can be used to launch Sonar analyses. - * </p> - * <p> - * Configuration is all done through properties: - * </p> - * <ul> - * <li>"sonar.projectDir": the base directory of the project to analyse (this can also be passed via the {@link #create(Properties, File)} constructor)</li> - * <li>"sonar.working.directory": the working directory, which is "${sonar.projectDir}/.sonar" by default.</li> - * <li>"sonar.verbose": if set to "true", more information is displayed in the log</li> - * <li>"sonar.environment.information.key" and "sonar.environment.information.version": can be used to overwrite environment information (can also be - * set via {@link #setEnvironmentInformation(String, String)} method)</li> - * <li>... plus all the other Sonar and Sonar plugins properties.</li> - * </ul> - * - * @since 1.1 - */ -public final class Runner { - - /** - * Old property used to activate debug level for logging. - * - * @deprecated Replaced by sonar.verbose since 1.2 - */ - @Deprecated - public static final String PROPERTY_OLD_DEBUG_MODE = "runner.debug"; - - /** - * Property used to increase logging information. - * - * @since 1.2 - */ - public static final String PROPERTY_VERBOSE = "sonar.verbose"; - - /** - * Property used to specify the working directory for the runner. May be a relative or absolute path. - * - * @since 1.4 - */ - public static final String PROPERTY_WORK_DIRECTORY = "sonar.working.directory"; - - /** - * Default value of the working directory. - */ - public static final String DEF_VALUE_WORK_DIRECTORY = ".sonar"; - - /** - * Property used to specify the base directory of the project to analyse. - * - * @since 1.5 - */ - public static final String PROPERTY_SONAR_PROJECT_BASEDIR = "sonar.projectBaseDir"; - - /** - * Property used to specify the name of the tool that will run a Sonar analysis. - * - * @since 1.5 - */ - public static final String PROPERTY_ENVIRONMENT_INFORMATION_KEY = "sonar.environment.information.key"; - - /** - * Property used to specify the version of the tool that will run a Sonar analysis. - * - * @since 1.5 - */ - public static final String PROPERTY_ENVIRONMENT_INFORMATION_VERSION = "sonar.environment.information.version"; - - /** - * Property used to define cache location (default to ~/.sonar/cache). - * - * @since 2.1 - */ - String ENV_SONAR_USER_HOME = "SONAR_USER_HOME"; - String PROPERTY_SONAR_USER_HOME = "sonar.userHome"; - - /** - * Array of prefixes of versions of Sonar without support of this runner. - */ - private static final String[] UNSUPPORTED_VERSIONS = {"1", "2.0", "2.1", "2.2", "2.3", "2.4", "2.5", "2.6", "2.7", "2.8", "2.9", "2.10"}; - private static final String[] UNSUPPORTED_VERSIONS_FOR_TASKS = {"1", "2", "3.0", "3.1", "3.2", "3.3", "3.4"}; - - private static final String PROPERTY_SOURCE_ENCODING = "sonar.sourceEncoding"; - - private String command; - private File projectDir; - private File sonarUserHomeDir; - private File workDir; - private String[] unmaskedPackages; - private List<Object> containerExtensions = new ArrayList<Object>(); - private Properties globalProperties; - private Properties projectProperties; - private boolean isEncodingPlatformDependant; - private SonarCache cache; - - private Runner(String command, Properties globalProperties, Properties projectProperties) { - this.command = command; - this.globalProperties = globalProperties; - this.projectProperties = projectProperties; - this.unmaskedPackages = new String[0]; - // set the default values for the Sonar Runner - they can be overriden with #setEnvironmentInformation - this.globalProperties.put(PROPERTY_ENVIRONMENT_INFORMATION_KEY, "Runner"); - this.globalProperties.put(PROPERTY_ENVIRONMENT_INFORMATION_VERSION, Version.getVersion()); - // sets the encoding if not forced - if (!globalProperties.containsKey(PROPERTY_SOURCE_ENCODING) && !projectProperties.containsKey(PROPERTY_SOURCE_ENCODING)) { - isEncodingPlatformDependant = true; - globalProperties.setProperty(PROPERTY_SOURCE_ENCODING, Charset.defaultCharset().name()); - } - // and init the directories - initDirs(); - // init the cache - // Try to get Sonar user home from property - cache = SonarCache.create(getSonarUserHomeDir()).build(); - } - - /** - * Creates a Runner based only on the given properties. - * @deprecated Use {@link Runner#create(String, Properties, Properties)} - */ - @Deprecated - public static Runner create(Properties props) { - return create(null, new Properties(), props); - } - - /** - * Creates a Runner based only on the given properties. - */ - public static Runner create(String command, Properties globalProperties, Properties projectProperties) { - return new Runner(command, globalProperties, projectProperties); - } - - /** - * Creates a Runner based only on the properties and with the given base directory. - * @deprecated Use {@link Runner#create(String, Properties, Properties, File)} - */ - @Deprecated - public static Runner create(Properties props, File basedir) { - return create(null, new Properties(), props, basedir); - } - - /** - * Creates a Runner based only on the properties and with the given base directory. - */ - public static Runner create(String command, Properties globalProperties, Properties projectProperties, File basedir) { - projectProperties.put(PROPERTY_SONAR_PROJECT_BASEDIR, basedir.getAbsolutePath()); - return new Runner(command, globalProperties, projectProperties); - } - - /** - * Runs a Sonar analysis. - */ - public void execute() { - Bootstrapper bootstrapper = new Bootstrapper("SonarRunner/" + Version.getVersion(), getSonarServerURL(), getWorkDir(), getCache()); - checkSonarVersion(bootstrapper); - delegateExecution(createClassLoader(bootstrapper)); - } - - public String getSonarServerURL() { - return projectProperties.getProperty("sonar.host.url", globalProperties.getProperty("sonar.host.url", "http://localhost:9000")); - } - - public SonarCache getCache() { - return cache; - } - - private void initDirs() { - projectDir = initProjectDir(); - // project home exists: add its absolute path as "sonar.projectBaseDir" property - projectProperties.put(PROPERTY_SONAR_PROJECT_BASEDIR, projectDir.getAbsolutePath()); - workDir = initWorkDir(); - sonarUserHomeDir = initSonarUserHomeDir(); - } - - private File initSonarUserHomeDir() { - String sonarUserHome = globalProperties.getProperty(PROPERTY_SONAR_USER_HOME); - if (StringUtils.isBlank(sonarUserHome)) { - // Try to get Sonar user home from environment variable - sonarUserHome = System.getenv(ENV_SONAR_USER_HOME); - } - if (StringUtils.isBlank(sonarUserHome)) { - // Default Sonar user home - sonarUserHome = System.getProperty("user.home") + File.separator + ".sonar"; - } - return new File(sonarUserHome); - } - - private File initProjectDir() { - String path = projectProperties.getProperty(PROPERTY_SONAR_PROJECT_BASEDIR, "."); - File dir = new File(path); - if (!dir.isDirectory()) { - throw new RunnerException("Project home must be an existing directory: " + path); - } - return dir; - } - - private File initWorkDir() { - File newWorkDir; - String customWorkDir = projectProperties.getProperty(PROPERTY_WORK_DIRECTORY, globalProperties.getProperty(PROPERTY_WORK_DIRECTORY)); - if (customWorkDir == null || "".equals(customWorkDir.trim())) { - newWorkDir = new File(getProjectDir(), DEF_VALUE_WORK_DIRECTORY); - } - else { - newWorkDir = defineCustomizedWorkDir(new File(customWorkDir)); - } - FileUtils.deleteQuietly(newWorkDir); - return newWorkDir; - } - - private File defineCustomizedWorkDir(File customWorkDir) { - if (customWorkDir.isAbsolute()) { - return customWorkDir; - } - return new File(getProjectDir(), customWorkDir.getPath()); - } - - /** - * @return the project base directory - */ - public File getProjectDir() { - return projectDir; - } - - /** - * @return work directory, default is ".sonar" in project directory - */ - public File getWorkDir() { - return workDir; - } - - /** - * @return sonar user home directory - */ - public File getSonarUserHomeDir() { - return sonarUserHomeDir; - } - - /** - * @return the source code encoding that will be used by Sonar - */ - public String getSourceCodeEncoding() { - return projectProperties.getProperty(PROPERTY_SOURCE_ENCODING, globalProperties.getProperty(PROPERTY_SOURCE_ENCODING)); - } - - /** - * @return true if the property "sonar.sourceEncoding" hasn't been forced - */ - public boolean isEncodingPlatformDependant() { - return isEncodingPlatformDependant; - } - - public String getCommand() { - return command; - } - - /** - * @return global properties, project properties and command-line properties - */ - public Properties getProperties() { - Properties props = new Properties(); - props.putAll(globalProperties); - props.putAll(projectProperties); - return props; - } - - protected void checkSonarVersion(Bootstrapper bootstrapper) { - String serverVersion = bootstrapper.getServerVersion(); - if (isUnsupportedVersion(serverVersion)) { - throw new RunnerException("Sonar " + serverVersion - + " is not supported. Please upgrade Sonar to version 2.11 or more."); - } - if (command != null && isUnsupportedVersionForTasks(serverVersion)) { - throw new RunnerException("Sonar " + serverVersion - + " doesn't support tasks. Please upgrade Sonar to version 3.5 or more."); - } - } - - private BootstrapClassLoader createClassLoader(Bootstrapper bootstrapper) { - URL url = getJarPath(); - return bootstrapper.createClassLoader( - // Add JAR with Sonar Runner - it's a Jar which contains this class - new URL[] {url}, - getClass().getClassLoader(), - unmaskedPackages); - } - - /** - * For unknown reasons <code>getClass().getProtectionDomain().getCodeSource().getLocation()</code> doesn't work under Ant 1.7.0. - * So this is a workaround. - * - * @return Jar which contains this class - */ - public static URL getJarPath() { - String pathToClass = "/" + Runner.class.getName().replace('.', '/') + ".class"; - URL url = Runner.class.getResource(pathToClass); - if (url != null) { - String path = url.toString(); - String uri = null; - if (path.startsWith("jar:file:")) { - int bang = path.indexOf('!'); - uri = path.substring(4, bang); - } else if (path.startsWith("file:")) { - int tail = path.indexOf(pathToClass); - uri = path.substring(0, tail); - } - if (uri != null) { - try { - return new URL(uri); - } catch (MalformedURLException e) { - } - } - } - return null; - } - - static boolean isUnsupportedVersion(String version) { - return VersionUtils.isUnsupportedVersion(version, UNSUPPORTED_VERSIONS); - } - - static boolean isUnsupportedVersionForTasks(String version) { - return VersionUtils.isUnsupportedVersion(version, UNSUPPORTED_VERSIONS_FOR_TASKS); - } - - private void delegateExecution(BootstrapClassLoader sonarClassLoader) { - ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader(); - try { - Thread.currentThread().setContextClassLoader(sonarClassLoader); - Class<?> launcherClass = sonarClassLoader.findClass("org.sonar.runner.internal.batch.Launcher"); - Constructor<?> constructor = launcherClass.getConstructor(String.class, Properties.class, Properties.class, List.class); - Object launcher = constructor.newInstance(getCommand(), globalProperties, projectProperties, containerExtensions); - Method method = launcherClass.getMethod("execute"); - method.invoke(launcher); - } catch (InvocationTargetException e) { - // Unwrap original exception - throw new RunnerException("Unable to execute Sonar", e.getTargetException()); - } catch (Exception e) { - // Catch all other exceptions, which relates to reflection - throw new RunnerException("Unable to execute Sonar", e); - } finally { - Thread.currentThread().setContextClassLoader(oldContextClassLoader); - } - } - - /** - * Allows to overwrite the environment information when Sonar Runner is embedded in a specific tool (for instance, with the Sonar Ant Task). - * - * @param key the key of the tool that embeds Sonar Runner - * @param version the version of this tool - */ - public void setEnvironmentInformation(String key, String version) { - this.globalProperties.put(PROPERTY_ENVIRONMENT_INFORMATION_KEY, key); - this.globalProperties.put(PROPERTY_ENVIRONMENT_INFORMATION_VERSION, version); - } - - public void setUnmaskedPackages(String... unmaskedPackages) { - this.unmaskedPackages = unmaskedPackages; - } - - public void addContainerExtension(Object extension) { - containerExtensions.add(extension); - } - -} diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/SonarCache.java b/sonar-runner-api/src/main/java/org/sonar/runner/SonarCache.java deleted file mode 100644 index cd8ae28..0000000 --- a/sonar-runner-api/src/main/java/org/sonar/runner/SonarCache.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * 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.codec.digest.DigestUtils; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.IOUtils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; - -/** - * This class is responsible for managing Sonar batch file cache. You can put file into cache and - * later try to retrieve them. MD5 is used to differentiate files (name is not secure as files may come - * from different Sonar servers and have same name but be actually different, and same for SNAPSHOTs). - * Default location of cache is - * @author Julien HENRY - * - */ -public class SonarCache { - - private static final int TEMP_FILE_ATTEMPTS = 10000; - - private File cacheLocation; - /** - * Temporary directory where files should be stored before be inserted in the cache. - * Having a temporary close to the final location (read on same FS) will assure - * the move will be atomic. - */ - private File tmpDir; - - private SonarCache(File cacheLocation) { - this.cacheLocation = cacheLocation; - tmpDir = new File(cacheLocation, "tmp"); - if (!cacheLocation.exists()) { - Logs.debug("Creating cache directory: " + cacheLocation.getAbsolutePath()); - try { - FileUtils.forceMkdir(cacheLocation); - } catch (IOException e) { - throw new RuntimeException("Unable to create cache directory " + cacheLocation.getAbsolutePath(), e); - } - } - } - - public static class Builder { - - private File sonarUserHomeLocation; - private File cacheLocation; - - public Builder(File sonarUserHomeLocation) { - this.sonarUserHomeLocation = sonarUserHomeLocation; - } - - public Builder setCacheLocation(File cacheLocation) { - this.cacheLocation = cacheLocation; - return this; - } - - public SonarCache build() { - if (cacheLocation == null) { - return new SonarCache(new File(sonarUserHomeLocation, "cache")); - } - else { - return new SonarCache(cacheLocation); - } - } - } - - public static Builder create(File sonarUserHomeLocation) { - if (sonarUserHomeLocation == null) { - throw new RunnerException("Sonar user home directory should not be null"); - } - return new Builder(sonarUserHomeLocation); - } - - /** - * Move the given file inside the cache. Return the MD5 of the cached file. - * @param sourceFile - * @throws IOException - */ - public String cacheFile(File sourceFile, String filename) throws IOException { - Logs.debug("Trying to cache file " + sourceFile.getAbsolutePath() + " with filename " + filename); - File tmpFileName = null; - try { - if (!sourceFile.getParentFile().equals(getTmpDir())) { - // Provided file is not close to the cache so we will move it first in a temporary file (could be non atomic) - tmpFileName = getTemporaryFile(); - FileUtils.moveFile(sourceFile, tmpFileName); - } - else { - tmpFileName = sourceFile; - } - // Now compute the md5 to find the final destination - String md5; - FileInputStream fis = null; - try { - fis = new FileInputStream(tmpFileName); - md5 = DigestUtils.md5Hex(fis); - } finally { - IOUtils.closeQuietly(fis); - } - File finalDir = new File(cacheLocation, md5); - File finalFileName = new File(finalDir, filename); - // Try to create final destination folder - FileUtils.forceMkdir(finalDir); - // Now try to move the file from temporary folder to final location - boolean rename = tmpFileName.renameTo(finalFileName); - if (!rename) { - // Check if the file was already in cache - if (!finalFileName.exists()) { - Logs.warn("Unable to rename " + tmpFileName.getAbsolutePath() + " to " + finalFileName.getAbsolutePath()); - Logs.warn("A copy/delete will be tempted but with no garantee of atomicity"); - FileUtils.moveFile(tmpFileName, finalFileName); - } - } - Logs.debug("File cached at " + finalFileName.getAbsolutePath()); - return md5; - } finally { - FileUtils.deleteQuietly(tmpFileName); - } - - } - - /** - * Look for a file in the cache by its filename and md5 checksum. If the file is not - * present then return null. - */ - public File getFileFromCache(String filename, String md5) { - File location = new File(new File(cacheLocation, md5), filename); - Logs.debug("Looking for " + location.getAbsolutePath()); - if (location.exists()) { - return location; - } - Logs.debug("No file found in the cache with name " + filename + " and checksum " + md5); - return null; - } - - /** - * Return a temporary file that caller can use to store file content before - * asking for caching it with {@link #cacheFile(File)}. - * This is to avoid extra copy. - * @return - * @throws IOException - */ - public File getTemporaryFile() throws IOException { - return createTempFile(getTmpDir()); - } - - /** - * Create a temporary file in the given directory. - * @param baseDir - * @return - * @throws IOException - */ - private static File createTempFile(File baseDir) throws IOException { - String baseName = System.currentTimeMillis() + "-"; - - for (int counter = 0; counter < TEMP_FILE_ATTEMPTS; counter++) { - File tempFile = new File(baseDir, baseName + counter); - if (tempFile.createNewFile()) { - return tempFile; - } - } - throw new IOException("Failed to create temporary file in " + baseDir.getAbsolutePath() + " within " - + TEMP_FILE_ATTEMPTS + " attempts (tried " - + baseName + "0 to " + baseName + (TEMP_FILE_ATTEMPTS - 1) + ')'); - } - - public File getTmpDir() { - if (!tmpDir.exists()) { - Logs.debug("Creating temporary cache directory: " + tmpDir.getAbsolutePath()); - try { - FileUtils.forceMkdir(tmpDir); - } catch (IOException e) { - throw new RuntimeException("Unable to create temporary cache directory " + tmpDir.getAbsolutePath(), e); - } - } - return tmpDir; - } - - public File getCacheLocation() { - return cacheLocation; - } -} diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/Stats.java b/sonar-runner-api/src/main/java/org/sonar/runner/Stats.java deleted file mode 100644 index b5ce8d5..0000000 --- a/sonar-runner-api/src/main/java/org/sonar/runner/Stats.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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; - -class Stats { - private long startTime; - - Stats() { - } - - Stats start() { - startTime = System.currentTimeMillis(); - return this; - } - - Stats stop() { - long stopTime = System.currentTimeMillis() - startTime; - Logs.info("Total time: " + formatTime(stopTime)); - - System.gc(); - Runtime r = Runtime.getRuntime(); - long mb = 1024L * 1024; - Logs.info("Final Memory: " + (r.totalMemory() - r.freeMemory()) / mb + "M/" + r.totalMemory() / mb + "M"); - - return this; - } - - static String formatTime(long time) { - long h = time / (60 * 60 * 1000); - long m = (time - h * 60 * 60 * 1000) / (60 * 1000); - long s = (time - h * 60 * 60 * 1000 - m * 60 * 1000) / 1000; - long ms = time % 1000; - final String format; - if (h > 0) { - format = "%1$d:%2$02d:%3$02d.%4$03ds"; - } else if (m > 0) { - format = "%2$d:%3$02d.%4$03ds"; - } else { - format = "%3$d.%4$03ds"; - } - return String.format(format, h, m, s, ms); - } -} diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/api/Command.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/Command.java new file mode 100644 index 0000000..89f9fbe --- /dev/null +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/Command.java @@ -0,0 +1,123 @@ +/* + * 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.api; + +import java.io.File; +import java.util.*; + +class Command { + private final String executable; + private final List<String> arguments; + private final Map<String, String> env; + private final File directory; + + private Command(Builder builder) { + this.executable = builder.executable; + this.arguments = Collections.unmodifiableList(builder.arguments); + this.env = Collections.unmodifiableMap(builder.env); + this.directory = builder.directory; + } + + File directory() { + return directory; + } + + String executable() { + return executable; + } + + List<String> arguments() { + return arguments; + } + + /** + * Environment variables that are propagated during command execution. + * + * @return a non-null and immutable map of variables + */ + Map<String, String> envVariables() { + return env; + } + + String[] toStrings() { + String[] strings = new String[1 + arguments.size()]; + strings[0] = executable; + for (int index = 0; index < arguments.size(); index++) { + strings[index + 1] = arguments.get(index); + } + return strings; + } + + @Override + public String toString() { + return Utils.join(toStrings(), " "); + } + + static Builder builder() { + return new Builder(); + } + + static class Builder { + private String executable; + private final List<String> arguments = new ArrayList<String>(); + private final Map<String, String> env = new HashMap<String, String>(); + private File directory; + + private Builder() { + } + + Builder setExecutable(String s) { + this.executable = s; + return this; + } + + Builder addArguments(String... args) { + arguments.addAll(Arrays.asList(args)); + return this; + } + + Builder addArguments(List<String> args) { + arguments.addAll(args); + return this; + } + + Builder setEnvVariable(String key, String value) { + env.put(key, value); + return this; + } + + Builder addEnvVariables(Map<String, String> map) { + env.putAll(map); + return this; + } + + Builder setDirectory(File d) { + this.directory = d; + return this; + } + + Command build() { + if (executable == null) { + throw new IllegalArgumentException("Command executable is not defined"); + } + return new Command(this); + } + } +} diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/api/CommandException.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/CommandException.java new file mode 100644 index 0000000..ba068e3 --- /dev/null +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/CommandException.java @@ -0,0 +1,30 @@ +/* + * 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.api; + +import javax.annotation.Nullable; + +class CommandException extends RuntimeException { + + CommandException(String message, Command command, @Nullable Throwable throwable) { + super(message + " [command: " + command + "]", throwable); + } + +} diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/api/CommandExecutor.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/CommandExecutor.java new file mode 100644 index 0000000..e3ac470 --- /dev/null +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/CommandExecutor.java @@ -0,0 +1,195 @@ +/* + * 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.api; + +import org.apache.commons.io.IOUtils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +/** + * Synchronously execute a native command line. It's much more limited than the Apache Commons Exec library. + * For example it does not allow to run asynchronously or to automatically quote command-line arguments. + * + * @since 2.7 + */ +class CommandExecutor { + + private static final CommandExecutor INSTANCE = new CommandExecutor(); + + private CommandExecutor() { + } + + static CommandExecutor create() { + // stateless object, so a single singleton can be shared + return INSTANCE; + } + + int execute(Command command, StreamConsumer stdOut, StreamConsumer stdErr, long timeoutMilliseconds) { + ExecutorService executorService = null; + Process process = null; + StreamGobbler outputGobbler = null; + StreamGobbler errorGobbler = null; + try { + ProcessBuilder builder = new ProcessBuilder(command.toStrings()); + if (command.directory() != null) { + builder.directory(command.directory()); + } + builder.environment().putAll(command.envVariables()); + process = builder.start(); + + outputGobbler = new StreamGobbler(process.getInputStream(), stdOut); + errorGobbler = new StreamGobbler(process.getErrorStream(), stdErr); + outputGobbler.start(); + errorGobbler.start(); + + final Process finalProcess = process; + executorService = Executors.newSingleThreadExecutor(); + Future<Integer> ft = executorService.submit(new Callable<Integer>() { + public Integer call() throws Exception { + return finalProcess.waitFor(); + } + }); + int exitCode = ft.get(timeoutMilliseconds, TimeUnit.MILLISECONDS); + waitUntilFinish(outputGobbler); + waitUntilFinish(errorGobbler); + verifyGobbler(command, outputGobbler, "stdOut"); + verifyGobbler(command, errorGobbler, "stdErr"); + return exitCode; + + } catch (TimeoutException te) { + process.destroy(); + throw new CommandException("Timeout exceeded: " + timeoutMilliseconds + " ms", command, te); + + } catch (CommandException e) { + throw e; + + } catch (Exception e) { + throw new CommandException("Fail to execute command", command, e); + + } finally { + waitUntilFinish(outputGobbler); + waitUntilFinish(errorGobbler); + closeStreams(process); + + if (executorService != null) { + executorService.shutdown(); + } + } + } + + private void verifyGobbler(Command command, StreamGobbler gobbler, String type) { + if (gobbler.getException() != null) { + throw new CommandException("Error inside " + type + " stream", command, gobbler.getException()); + } + } + + /** + * Execute command and display error and output streams in log. + * Method {@link #execute(Command, StreamConsumer, StreamConsumer, long)} is preferable, + * when fine-grained control of output of command required. + */ + int execute(Command command, long timeoutMilliseconds) { + return execute(command, new DefaultConsumer(), new DefaultConsumer(), timeoutMilliseconds); + } + + private void closeStreams(Process process) { + if (process != null) { + IOUtils.closeQuietly(process.getInputStream()); + IOUtils.closeQuietly(process.getInputStream()); + IOUtils.closeQuietly(process.getOutputStream()); + IOUtils.closeQuietly(process.getErrorStream()); + } + } + + private void waitUntilFinish(StreamGobbler thread) { + if (thread != null) { + try { + thread.join(); + } catch (InterruptedException e) { + System.err.println("InterruptedException while waiting finish of " + thread.toString()); + e.printStackTrace(); + } + } + } + + private static class StreamGobbler extends Thread { + private final InputStream is; + private final StreamConsumer consumer; + private volatile Exception exception; + + StreamGobbler(InputStream is, StreamConsumer consumer) { + super("ProcessStreamGobbler"); + this.is = is; + this.consumer = consumer; + } + + @Override + public void run() { + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + try { + String line; + while ((line = br.readLine()) != null) { + consumeLine(line); + } + } catch (IOException ioe) { + exception = ioe; + + } finally { + IOUtils.closeQuietly(br); + IOUtils.closeQuietly(isr); + } + } + + private void consumeLine(String line) { + if (exception == null) { + try { + consumer.consumeLine(line); + } catch (Exception e) { + exception = e; + } + } + } + + public Exception getException() { + return exception; + } + } + + + interface StreamConsumer { + void consumeLine(String line); + } + + private static class DefaultConsumer implements StreamConsumer { + public void consumeLine(String line) { + System.out.println(line); + } + } +} diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/Logs.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/EmbeddedRunner.java index b7da73c..3357e9a 100644 --- a/sonar-runner-api/src/main/java/org/sonar/runner/Logs.java +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/EmbeddedRunner.java @@ -17,44 +17,40 @@ * 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; +package org.sonar.runner.api; -final class Logs { - private Logs() { - } +import org.sonar.runner.impl.BatchLauncher; - private static boolean debugEnabled = false; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; - public static void setDebugEnabled(boolean debugEnabled) { - Logs.debugEnabled = debugEnabled; - } +public class EmbeddedRunner extends Runner<EmbeddedRunner> { + + private final List<Object> extensions = new ArrayList<Object>(); - public static boolean isDebugEnabled() { - return debugEnabled; + private EmbeddedRunner() { } - static void debug(String message) { - if (isDebugEnabled()) { - System.out.println("DEBUG: " + message); - } + public static EmbeddedRunner create() { + return new EmbeddedRunner(); } - static void info(String message) { - System.out.println("INFO: " + message); + public EmbeddedRunner setUnmaskedPackages(String... packages) { + return setProperty("sonarRunner.unmaskedPackages", Utils.join(packages, ",")); } - static void warn(String message) { - System.out.println("WARN: " + message); + public EmbeddedRunner addExtensions(Object... objects) { + extensions.addAll(Arrays.asList(objects)); + return this; } - static void error(String message) { - System.err.println("ERROR: " + message); + List<Object> extensions() { + return extensions; } - static void error(String message, Throwable t) { - System.err.println("ERROR: " + message); - if (t != null) { - t.printStackTrace(System.err); - } + @Override + public void doExecute() { + new BatchLauncher().execute(properties(), extensions); } } diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/api/ForkedRunner.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/ForkedRunner.java new file mode 100644 index 0000000..7a6c3cc --- /dev/null +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/ForkedRunner.java @@ -0,0 +1,118 @@ +/* + * 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.api; + +import org.apache.commons.io.IOUtils; +import org.sonar.runner.impl.BatchLauncherMain; +import org.sonar.runner.impl.JarExtractor; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class ForkedRunner extends Runner<ForkedRunner> { + + private static final int ONE_DAY_IN_MILLISECONDS = 24 * 60 * 60 * 1000; + + private final Command.Builder commandBuilder; + private final JarExtractor jarExtractor; + + ForkedRunner(Command.Builder commandBuilder, JarExtractor jarExtractor) { + this.commandBuilder = commandBuilder; + this.jarExtractor = jarExtractor; + } + + public static ForkedRunner create() { + Os os = new Os(); + Command.Builder builder = Command.builder().setExecutable(os.usedJavaExe().getAbsolutePath()); + return new ForkedRunner(builder, new JarExtractor()); + } + + @Override + public void doExecute() { + File propertiesFile = writeProperties(); + File jarFile = extractJar(); + fork(jarFile, propertiesFile); + } + + private File extractJar() { + return jarExtractor.extract("sonar-runner-impl"); + } + + private void fork(File jarFile, File propertiesFile) { + // java -jar sonar-runner-impl.jar path/to/propertiesFile + Command command = commandBuilder + .addArguments("-cp", jarFile.getAbsolutePath()) + .addArguments(BatchLauncherMain.class.getName()) + .addArguments(propertiesFile.getAbsolutePath()) + .build(); + System.out.println("---------- execute: " + command); + int status = CommandExecutor.create().execute(command, ONE_DAY_IN_MILLISECONDS); + if (status != 0) { + throw new IllegalStateException("TODO"); + } + } + + private File writeProperties() { + OutputStream output = null; + try { + File file = File.createTempFile("sonar-project", ".properties"); + output = new FileOutputStream(file); + properties().store(output, "Generated by sonar-runner"); + return file; + + } catch (Exception e) { + throw new IllegalStateException("Fail to export sonar-runner properties", e); + + } finally { + IOUtils.closeQuietly(output); + } + } + + public ForkedRunner setJavaCommand(String s) { + commandBuilder.setExecutable(s); + return this; + } + + public ForkedRunner addJvmArgument(String... s) { + commandBuilder.addArguments(Arrays.asList(s)); + return this; + } + + public ForkedRunner addJvmArguments(List<String> args) { + commandBuilder.addArguments(args); + return this; + } + + public ForkedRunner setJvmEnvVariable(String key, String value) { + commandBuilder.setEnvVariable(key, value); + return this; + } + + public ForkedRunner addJvmEnvVariables(Map<String, String> map) { + commandBuilder.addEnvVariables(map); + return this; + } + + +} diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/RunnerException.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/Os.java index a676f57..da51361 100644 --- a/sonar-runner-api/src/main/java/org/sonar/runner/RunnerException.java +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/Os.java @@ -17,36 +17,24 @@ * 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; +package org.sonar.runner.api; -/** - * Exception thrown by the Sonar Runner when something bad happens. - * - * @since 1.2 - */ -public class RunnerException extends RuntimeException { - - private static final long serialVersionUID = 4810407777585753030L; +import java.io.File; - /** - * See {@link RuntimeException} - */ - public RunnerException(String message) { - super(message); +class Os { + boolean isWindows() { + return System.getProperty("os.name").contains("Windows"); } - /** - * See {@link RuntimeException} - */ - public RunnerException(Throwable cause) { - super(cause); + File usedJavaHome() { + return new File(System.getProperty("java.home")); } /** - * See {@link RuntimeException} + * Path to the java executable used by this VM */ - public RunnerException(String message, Throwable cause) { - super(message, cause); + File usedJavaExe() { + File bin = new File(usedJavaHome(), "bin"); + return new File(bin, isWindows() ? "java.exe" : "java"); } - } diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/api/Runner.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/Runner.java new file mode 100644 index 0000000..079cdb9 --- /dev/null +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/Runner.java @@ -0,0 +1,102 @@ +/* + * 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.api; + +import org.sonar.runner.impl.Constants; +import org.sonar.runner.impl.Logs; + +import javax.annotation.Nullable; + +import java.nio.charset.Charset; +import java.util.Locale; +import java.util.Properties; + +/** + * @since 2.2 + */ +public abstract class Runner<T extends Runner> { + + private final Properties properties = new Properties(); + + protected Runner() { + initProperties(); + } + + private void initProperties() { + // default values + properties.put(Constants.HOST_URL, "http://localhost:9000"); + properties.put(Constants.TASK, "scan"); + properties.put(Constants.PROP_APP, "SonarRunner"); + properties.put(Constants.PROP_APP_VERSION, RunnerVersion.version()); + } + + public Properties properties() { + Properties clone = new Properties(); + clone.putAll(properties); + return clone; + } + + public T addProperties(Properties p) { + properties.putAll(p); + return (T) this; + } + + public T setProperty(String key, String value) { + properties.setProperty(key, value); + return (T) this; + } + + public String property(String key, @Nullable String defaultValue) { + return properties.getProperty(key, defaultValue); + } + + public T setApp(String app, String version) { + setProperty(Constants.PROP_APP, app); + setProperty(Constants.PROP_APP_VERSION, version); + return (T) this; + } + + public String app() { + return property(Constants.PROP_APP, null); + } + + public String appVersion() { + return property(Constants.PROP_APP_VERSION, null); + } + + public void execute() { + initSourceEncoding(); + doExecute(); + } + + private void initSourceEncoding() { + String sourceEncoding = property(Constants.SOURCE_ENCODING, null); + boolean platformDependent = false; + if (sourceEncoding == null || sourceEncoding.equals("")) { + sourceEncoding = Charset.defaultCharset().name(); + platformDependent = true; + setProperty(Constants.SOURCE_ENCODING, sourceEncoding); + } + Logs.info("Default locale: \"" + Locale.getDefault() + "\", source code encoding: \"" + sourceEncoding + "\"" + + (platformDependent ? " (analysis is platform dependent)" : "")); + } + + protected abstract void doExecute(); +} diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/Version.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/RunnerVersion.java index e0447c0..d15f72f 100644 --- a/sonar-runner-api/src/main/java/org/sonar/runner/Version.java +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/RunnerVersion.java @@ -17,38 +17,26 @@ * 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; +package org.sonar.runner.api; -import org.apache.commons.io.IOUtils; +import java.util.Scanner; -import java.io.IOException; -import java.io.InputStream; -import java.util.Properties; - -public enum Version { +public enum RunnerVersion { INSTANCE; - private static final String PROPERTIES_PATH = "/org/sonar/runner/version.txt"; private String version; - public static String getVersion() { + public static String version() { return INSTANCE.version; } - private Version() { - InputStream input = getClass().getResourceAsStream(PROPERTIES_PATH); + private RunnerVersion() { + Scanner scanner = new Scanner(getClass().getResourceAsStream("/org/sonar/runner/api/version.txt"), "UTF-8"); try { - Properties properties = new Properties(); - properties.load(input); - this.version = properties.getProperty("version"); - - } catch (IOException e) { - // Can not load the version - this.version = ""; - + this.version = scanner.next(); } finally { - IOUtils.closeQuietly(input); + scanner.close(); } } } diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/VersionUtils.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/Utils.java index 3e19df8..9be34b8 100644 --- a/sonar-runner-api/src/main/java/org/sonar/runner/VersionUtils.java +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/Utils.java @@ -17,29 +17,25 @@ * 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; +package org.sonar.runner.api; -/** - * Internal class used only by the Runner. - * This class should not be used by Sonar Runner consumers. - */ -final class VersionUtils { - - private VersionUtils() { - // only static methods - } +import java.util.Arrays; +import java.util.Iterator; - static boolean isUnsupportedVersion(String version, String[] unsuportedVersions) { - for (String unsupportedVersion : unsuportedVersions) { - if (isVersion(version, unsupportedVersion)) { - return true; +class Utils { + /** + * Similar to org.apache.commons.lang.StringUtils#join() + */ + static String join(String[] array, String delimiter) { + StringBuilder sb = new StringBuilder(); + Iterator it = Arrays.asList(array).iterator(); + while (it.hasNext()) { + sb.append(it.next()); + if (!it.hasNext()) { + break; } + sb.append(delimiter); } - return false; + return sb.toString(); } - - private static boolean isVersion(String version, String prefix) { - return version.startsWith(prefix + ".") || version.equals(prefix); - } - } diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/package-info.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/package-info.java index e837d88..a362ee1 100644 --- a/sonar-runner-api/src/main/java/org/sonar/runner/package-info.java +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/package-info.java @@ -17,7 +17,7 @@ * License along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 */ -/** - * API package of the Sonar Runner. - */ -package org.sonar.runner;
\ No newline at end of file +@ParametersAreNonnullByDefault +package org.sonar.runner.api; + +import javax.annotation.ParametersAreNonnullByDefault;
\ No newline at end of file diff --git a/sonar-runner-api/src/main/resources/org/sonar/runner/api/version.txt b/sonar-runner-api/src/main/resources/org/sonar/runner/api/version.txt new file mode 100644 index 0000000..f2ab45c --- /dev/null +++ b/sonar-runner-api/src/main/resources/org/sonar/runner/api/version.txt @@ -0,0 +1 @@ +${project.version}
\ No newline at end of file diff --git a/sonar-runner-api/src/main/resources/org/sonar/runner/version.txt b/sonar-runner-api/src/main/resources/org/sonar/runner/version.txt deleted file mode 100644 index defbd48..0000000 --- a/sonar-runner-api/src/main/resources/org/sonar/runner/version.txt +++ /dev/null @@ -1 +0,0 @@ -version=${project.version} diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/BootstrapClassLoaderTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/BootstrapClassLoaderTest.java deleted file mode 100644 index 7917d2d..0000000 --- a/sonar-runner-api/src/test/java/org/sonar/runner/BootstrapClassLoaderTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static org.fest.assertions.Assertions.assertThat; - -public class BootstrapClassLoaderTest { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void should_restrict_loading_from_parent() throws Exception { - BootstrapClassLoader classLoader = new BootstrapClassLoader(getClass().getClassLoader(), "org.apache.ant"); - assertThat(classLoader.canLoadFromParent("org.sonar.runner.internal.batch.Launcher")).isFalse(); - assertThat(classLoader.canLoadFromParent("org.sonar.runner.Runner")).isTrue(); - assertThat(classLoader.canLoadFromParent("org.objectweb.asm.ClassVisitor")).isFalse(); - assertThat(classLoader.canLoadFromParent("org.apache.ant.project.Project")).isTrue(); - } - - @Test - public void should_use_isolated_system_classloader_when_parent_is_excluded() throws ClassNotFoundException { - thrown.expect(ClassNotFoundException.class); - thrown.expectMessage("org.junit.Test"); - ClassLoader parent = getClass().getClassLoader(); - BootstrapClassLoader classLoader = new BootstrapClassLoader(parent); - - // JUnit is available in the parent classloader (classpath used to execute this test) but not in the core JVM - assertThat(classLoader.loadClass("java.lang.String", false)).isNotNull(); - classLoader.loadClass("org.junit.Test", false); - } - - @Test - public void should_find_in_parent_when_matches_unmasked_packages() throws ClassNotFoundException { - ClassLoader parent = getClass().getClassLoader(); - BootstrapClassLoader classLoader = new BootstrapClassLoader(parent, "org.junit"); - - // JUnit is available in the parent classloader (classpath used to execute this test) but not in the core JVM - assertThat(classLoader.loadClass("org.junit.Test", false)).isNotNull(); - } -} diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/BootstrapperTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/BootstrapperTest.java deleted file mode 100644 index 37a5425..0000000 --- a/sonar-runner-api/src/test/java/org/sonar/runner/BootstrapperTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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 org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; - -import java.io.File; -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; - -import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class BootstrapperTest { - - @Rule - public TemporaryFolder tempFolder = new TemporaryFolder(); - - @Test - public void shouldRemoveLastUrlSlash() { - Bootstrapper bootstrapper = new Bootstrapper("", "http://test/", new File("target/tmp"), null); - assertThat(bootstrapper.getServerUrl()).isEqualTo("http://test"); - } - - @Test(expected = Exception.class) - public void shouldFailIfCanNotConnectServer() { - Bootstrapper bootstrapper = new Bootstrapper("", "http://unknown.foo", new File("target/tmp"), null); - bootstrapper.getServerVersion(); - } - - @Test - public void shouldReturnUserAgent() { - Bootstrapper bootstrapper = new Bootstrapper("test/0.1", "http://unknown.foo", new File("target/tmp"), null); - String userAgent = bootstrapper.getUserAgent(); - - assertThat(userAgent.length()).isGreaterThan(0); - assertThat(userAgent).startsWith("sonar-bootstrapper/"); - assertThat(userAgent).endsWith(" test/0.1"); - } - - @Test - public void shouldReturnValidVersion() { - Bootstrapper bootstrapper = new Bootstrapper("", "http://test", new File("target/tmp"), null) { - @Override - String remoteContent(String path) throws IOException { - return "2.6"; - } - }; - assertThat(bootstrapper.getServerVersion()).isEqualTo("2.6"); - } - - @Test - public void shouldParseEncodingFromContentType() { - assertThat(Bootstrapper.getCharsetFromContentType("text/html; charset=EUC-JP")).isEqualTo("EUC-JP"); - assertThat(Bootstrapper.getCharsetFromContentType("text/html")).isNull(); - } - - @Test - public void shouldCheckVersionForCache() { - assertThat(Bootstrapper.isUnsupportedVersionForCache("1.0")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("2.0")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("2.1")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("2.2")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("2.3")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("2.4")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("2.4.1")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("2.5")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("2.11")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("3.0")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("3.1")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("3.2")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("3.3")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("3.4")).isTrue(); - assertThat(Bootstrapper.isUnsupportedVersionForCache("3.5")).isFalse(); - } - - @Test - public void shouldCacheWhenNecessary() throws Exception { - File sonarUserHome = tempFolder.newFolder(); - SonarCache cache = SonarCache.create(sonarUserHome).build(); - final MockedConnectionFactory connections = new MockedConnectionFactory("http://test"); - connections.register("/api/server/version", "3.5"); - connections.register("/batch_bootstrap/index", "foo.jar|922afef30ca31573d7131347d01b76c4\nbar.jar|69155f65900fbabbf21e28abb33dd06a"); - connections.register("/batch/foo.jar", "fakecontent1"); - connections.register("/batch/bar.jar", "fakecontent2"); - Bootstrapper bootstrapper = new Bootstrapper("", "http://test", new File("target/tmp"), cache) { - @Override - HttpURLConnection newHttpConnection(URL url) throws IOException { - return connections.get(url); - } - }; - bootstrapper.createClassLoader(new URL[] {}, this.getClass().getClassLoader()); - assertThat(new File(new File(cache.getCacheLocation(), "922afef30ca31573d7131347d01b76c4"), "foo.jar")).exists(); - assertThat(new File(new File(cache.getCacheLocation(), "69155f65900fbabbf21e28abb33dd06a"), "bar.jar")).exists(); - - // Should not download during the second execution - final MockedConnectionFactory connections2 = new MockedConnectionFactory("http://test"); - connections2.register("/api/server/version", "3.5"); - connections2.register("/batch_bootstrap/index", "foo.jar|922afef30ca31573d7131347d01b76c4\nbar.jar|69155f65900fbabbf21e28abb33dd06a"); - Bootstrapper bootstrapper2 = new Bootstrapper("", "http://test", new File("target/tmp"), cache) { - @Override - HttpURLConnection newHttpConnection(URL url) throws IOException { - return connections2.get(url); - } - }; - bootstrapper2.createClassLoader(new URL[] {}, this.getClass().getClassLoader()); - } - - @Test - public void shouldDownloadFromOldURL() throws Exception { - File sonarUserHome = tempFolder.newFolder(); - final MockedConnectionFactory connections = new MockedConnectionFactory("http://test"); - connections.register("/api/server/version", "3.4"); - connections.register("/batch/", "foo.jar,bar.jar"); - connections.register("/batch/foo.jar", "fakecontent1"); - connections.register("/batch/bar.jar", "fakecontent2"); - Bootstrapper bootstrapper = new Bootstrapper("", "http://test", new File("target/tmp"), SonarCache.create(sonarUserHome).build()) { - @Override - HttpURLConnection newHttpConnection(URL url) throws IOException { - return connections.get(url); - } - }; - bootstrapper.createClassLoader(new URL[] {}, this.getClass().getClassLoader()); - verify(connections.get("/batch/foo.jar")).getInputStream(); - verify(connections.get("/batch/bar.jar")).getInputStream(); - } - - private class MockedConnectionFactory { - private Map<URL, HttpURLConnection> mockedConnections = new HashMap<URL, HttpURLConnection>(); - private String serverUrl; - - public MockedConnectionFactory(String serverUrl) { - this.serverUrl = serverUrl; - } - - public void register(String path, String content) throws Exception { - HttpURLConnection mockConnection = mock(HttpURLConnection.class); - when(mockConnection.getInputStream()).thenReturn(IOUtils.toInputStream(content)); - when(mockConnection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_OK); - mockedConnections.put(new URL(serverUrl + path), mockConnection); - } - - public HttpURLConnection get(URL url) { - return mockedConnections.get(url); - } - - public HttpURLConnection get(String path) throws MalformedURLException { - return mockedConnections.get(new URL(serverUrl + path)); - } - - } -} diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/LogsTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/LogsTest.java deleted file mode 100644 index 1131300..0000000 --- a/sonar-runner-api/src/test/java/org/sonar/runner/LogsTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; - -import static org.fest.assertions.Assertions.assertThat; - -public class LogsTest { - - private PrintStream oldSysout; - private PrintStream oldSyserr; - - private ByteArrayOutputStream baosOut; - private ByteArrayOutputStream baosErr; - - @Before - public void prepare() { - oldSysout = System.out; - oldSyserr = System.err; - baosOut = new ByteArrayOutputStream(); - System.setOut(new PrintStream(baosOut)); - baosErr = new ByteArrayOutputStream(); - System.setErr(new PrintStream(baosErr)); - } - - @After - public void restore() { - System.setOut(oldSysout); - System.setErr(oldSyserr); - } - - @Test - public void shouldLogInfo() { - Logs.info("info"); - assertThat(baosOut.toString()).contains("INFO: info"); - assertThat(baosErr.toString()).isEmpty(); - } - - @Test - public void shouldLogError() { - Logs.error("error"); - assertThat(baosOut.toString()).isEmpty(); - assertThat(baosErr.toString()).contains("ERROR: error"); - } - - @Test - public void shouldLogErrorWithoutThrowable() { - Logs.error("error", null); - assertThat(baosOut.toString()).isEmpty(); - assertThat(baosErr.toString()).contains("ERROR: error"); - } - - @Test - public void shouldLogErrorWithThrowable() { - Logs.error("error", new RuntimeException()); - assertThat(baosOut.toString()).isEmpty(); - assertThat(baosErr.toString()).contains("ERROR: error").contains("RuntimeException"); - } - -} diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/MainTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/MainTest.java deleted file mode 100644 index de7f17c..0000000 --- a/sonar-runner-api/src/test/java/org/sonar/runner/MainTest.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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.junit.Before; -import org.junit.Test; - -import java.io.File; -import java.util.Properties; - -import static org.fest.assertions.Assertions.assertThat; - -public class MainTest { - - private Main main; - - @Before - public void prepare() { - main = new Main(); - } - - @Test - public void shouldParseEmptyArguments() { - Properties props = main.parseArguments(new String[] {}); - assertThat(props).isEmpty(); - } - - @Test - public void shouldParseArguments() { - Properties props = main.parseArguments(new String[] {"-D", "foo=bar", "--define", "hello=world", "-Dboolean"}); - assertThat(props).hasSize(3); - assertThat(props.getProperty("foo")).isEqualTo("bar"); - assertThat(props.getProperty("hello")).isEqualTo("world"); - assertThat(props.getProperty("boolean")).isEqualTo("true"); - } - - @Test - public void shouldParseCommand() { - - Properties props = main.parseArguments(new String[] {"cmd", "-D", "foo=bar", "--define", "hello=world", "-Dboolean"}); - assertThat(main.command).isEqualTo("cmd"); - assertThat(props).hasSize(3); - } - - @Test - public void shouldEnableDebugMode() { - Properties props = main.parseArguments(new String[] {"-X"}); - assertThat(main.debugMode).isTrue(); - assertThat(main.displayStackTrace).isTrue(); - assertThat(props.getProperty(Runner.PROPERTY_VERBOSE)).isEqualTo("true"); - } - - @Test - public void shouldEnableError() { - Properties props = main.parseArguments(new String[] {"-e"}); - assertThat(main.debugMode).isFalse(); - assertThat(main.displayStackTrace).isTrue(); - assertThat(props.getProperty(Runner.PROPERTY_VERBOSE)).isNull(); - } - - @Test - public void shouldDisableDebugModeAndStackByDefault() { - Properties props = main.parseArguments(new String[] {}); - assertThat(main.debugMode).isFalse(); - assertThat(main.displayStackTrace).isFalse(); - assertThat(props.getProperty(Runner.PROPERTY_VERBOSE)).isNull(); - } - - @Test - public void shouldLoadRunnerSettingsByHome() throws Exception { - File home = new File(getClass().getResource("/org/sonar/runner/MainTest/shouldLoadRunnerSettingsByHome/").toURI()); - Properties args = new Properties(); - args.setProperty("runner.home", home.getCanonicalPath()); - - Properties props = new Main().loadRunnerConfiguration(args); - - assertThat(props.getProperty("sonar.host.url")).isEqualTo("http://moon/sonar"); - } - - @Test - public void shouldNotFailIfNoHome() throws Exception { - Properties args = new Properties(); - Properties props = new Main().loadRunnerConfiguration(args); - - assertThat(props).isEmpty(); - } - - @Test - public void shouldLoadRunnerSettingsByDirectPath() throws Exception { - File settings = new File(getClass().getResource("/org/sonar/runner/MainTest/shouldLoadRunnerSettingsByDirectPath/other-conf.properties").toURI()); - Properties args = new Properties(); - args.setProperty("runner.settings", settings.getCanonicalPath()); - Properties props = new Main().loadRunnerConfiguration(args); - - assertThat(props.getProperty("sonar.host.url")).isEqualTo("http://other/sonar"); - } - - @Test - public void shouldLoadCompleteConfiguration() throws Exception { - File runnerHome = new File(getClass().getResource("/org/sonar/runner/MainTest/shouldLoadCompleteConfiguration/runner").toURI()); - File projectHome = new File(getClass().getResource("/org/sonar/runner/MainTest/shouldLoadCompleteConfiguration/project").toURI()); - Main main = new Main(); - Properties args = main.parseArguments(new String[] { - "-D", "runner.home=" + runnerHome.getCanonicalPath(), - "-D", "project.home=" + projectHome.getCanonicalPath() - }); - main.loadProperties(args); - - assertThat(main.projectProperties.getProperty("project.prop")).isEqualTo("foo"); - assertThat(main.projectProperties.getProperty("overridden.prop")).isEqualTo("project scope"); - assertThat(main.globalProperties.getProperty("global.prop")).isEqualTo("jdbc:mysql:localhost/sonar"); - } - -} diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/RunnerTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/RunnerTest.java deleted file mode 100644 index 545565f..0000000 --- a/sonar-runner-api/src/test/java/org/sonar/runner/RunnerTest.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * 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.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; - -import java.io.File; -import java.nio.charset.Charset; -import java.util.Properties; - -import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class RunnerTest { - - @Rule - public TemporaryFolder tempFolder = new TemporaryFolder(); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void shouldHaveDefaultEncodingIfNotForce() { - Runner runner = Runner.create(new Properties()); - assertThat(runner.getSourceCodeEncoding()).isEqualTo(Charset.defaultCharset().name()); - assertThat(runner.isEncodingPlatformDependant()).isTrue(); - } - - @Test - public void shouldKeepEncodingIfSpecified() { - Properties props = new Properties(); - // Yeah, windows charset! - props.setProperty("sonar.sourceEncoding", "cp1252"); - Runner runner = Runner.create(props); - assertThat(runner.getSourceCodeEncoding()).isEqualTo("cp1252"); - assertThat(runner.isEncodingPlatformDependant()).isFalse(); - } - - @Test - public void shouldHaveDefaultEnvironmentInformationValues() { - Runner runner = Runner.create(new Properties()); - assertThat(runner.getProperties().getProperty(Runner.PROPERTY_ENVIRONMENT_INFORMATION_KEY)).isEqualTo("Runner"); - assertThat(runner.getProperties().getProperty(Runner.PROPERTY_ENVIRONMENT_INFORMATION_VERSION)).contains("."); - assertThat(runner.getProperties().getProperty(Runner.PROPERTY_ENVIRONMENT_INFORMATION_VERSION)).doesNotContain("$"); - } - - @Test - public void shouldOverwriteDefaultEnvironmentInformationValues() { - Runner runner = Runner.create(new Properties()); - runner.setEnvironmentInformation("Ant", "1.2.3"); - assertThat(runner.getProperties().getProperty(Runner.PROPERTY_ENVIRONMENT_INFORMATION_KEY)).isEqualTo("Ant"); - assertThat(runner.getProperties().getProperty(Runner.PROPERTY_ENVIRONMENT_INFORMATION_VERSION)).isEqualTo("1.2.3"); - } - - @Test - public void shouldCheckVersion() { - assertThat(Runner.isUnsupportedVersion("1.0")).isTrue(); - assertThat(Runner.isUnsupportedVersion("2.0")).isTrue(); - assertThat(Runner.isUnsupportedVersion("2.1")).isTrue(); - assertThat(Runner.isUnsupportedVersion("2.2")).isTrue(); - assertThat(Runner.isUnsupportedVersion("2.3")).isTrue(); - assertThat(Runner.isUnsupportedVersion("2.4")).isTrue(); - assertThat(Runner.isUnsupportedVersion("2.4.1")).isTrue(); - assertThat(Runner.isUnsupportedVersion("2.5")).isTrue(); - assertThat(Runner.isUnsupportedVersion("2.11")).isFalse(); - assertThat(Runner.isUnsupportedVersion("3.0")).isFalse(); - assertThat(Runner.isUnsupportedVersion("3.1")).isFalse(); - assertThat(Runner.isUnsupportedVersion("3.2")).isFalse(); - assertThat(Runner.isUnsupportedVersion("3.3")).isFalse(); - assertThat(Runner.isUnsupportedVersion("3.4")).isFalse(); - assertThat(Runner.isUnsupportedVersion("3.5")).isFalse(); - } - - @Test - public void shouldCheckVersionForTasks() { - assertThat(Runner.isUnsupportedVersionForTasks("1.0")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("2.0")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("2.1")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("2.2")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("2.3")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("2.4")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("2.4.1")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("2.5")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("2.11")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("3.0")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("3.1")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("3.2")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("3.3")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("3.4")).isTrue(); - assertThat(Runner.isUnsupportedVersionForTasks("3.5")).isFalse(); - } - - @Test - public void shouldGetServerUrl() { - Properties properties = new Properties(); - Runner runner = Runner.create(properties); - assertThat(runner.getSonarServerURL()).isEqualTo("http://localhost:9000"); - properties.setProperty("sonar.host.url", "foo"); - assertThat(runner.getSonarServerURL()).isEqualTo("foo"); - } - - @Test - public void shouldInitDirs() throws Exception { - Properties props = new Properties(); - File home = tempFolder.newFolder("shouldInitDirs").getCanonicalFile(); - props.setProperty(Runner.PROPERTY_SONAR_PROJECT_BASEDIR, home.getCanonicalPath()); - Runner runner = Runner.create(props); - assertThat(runner.getProperties().get(Runner.PROPERTY_SONAR_PROJECT_BASEDIR)).isEqualTo(home.getCanonicalPath()); - - assertThat(runner.getProjectDir().getCanonicalFile()).isEqualTo(home); - assertThat(runner.getWorkDir().getCanonicalFile()).isEqualTo(new File(home, ".sonar")); - } - - @Test - public void shouldInitProjectDirWithCurrentDir() throws Exception { - Runner runner = Runner.create(new Properties()); - - assertThat(runner.getProjectDir().isDirectory()).isTrue(); - assertThat(runner.getProjectDir().exists()).isTrue(); - } - - @Test - public void shouldSetValidBaseDirOnConstructor() { - File baseDir = tempFolder.newFolder("shouldInitDirs"); - Runner runner = Runner.create(new Properties(), baseDir); - assertThat(runner.getProjectDir()).isEqualTo(baseDir); - } - - @Test - public void shouldFailIfBaseDirDoesNotExist() { - File fakeBasedir = new File("fake"); - - thrown.expect(RunnerException.class); - thrown.expectMessage("Project home must be an existing directory: " + fakeBasedir.getAbsolutePath()); - - Runner.create(new Properties(), fakeBasedir); - } - - @Test - public void shouldSpecifyWorkingDirectory() { - Properties properties = new Properties(); - Runner runner = Runner.create(properties); - assertThat(runner.getWorkDir()).isEqualTo(new File(".", ".sonar")); - - // empty string - properties.setProperty(Runner.PROPERTY_WORK_DIRECTORY, " "); - runner = Runner.create(properties); - assertThat(runner.getWorkDir()).isEqualTo(new File(".", ".sonar").getAbsoluteFile()); - - // real relative path - properties.setProperty(Runner.PROPERTY_WORK_DIRECTORY, "temp-dir"); - runner = Runner.create(properties); - assertThat(runner.getWorkDir()).isEqualTo(new File(".", "temp-dir").getAbsoluteFile()); - - // real absolute path - properties.setProperty(Runner.PROPERTY_WORK_DIRECTORY, new File("target", "temp-dir2").getAbsolutePath()); - runner = Runner.create(properties); - assertThat(runner.getWorkDir()).isEqualTo(new File("target", "temp-dir2").getAbsoluteFile()); - } - - @Test - public void shouldDeleteWorkingDirectory() { - Properties properties = new Properties(); - File workDir = new File("target", "temp-dir-should-be-deleted"); - workDir.mkdirs(); - assertThat(workDir.exists()).isTrue(); - // real absolute path - properties.setProperty(Runner.PROPERTY_WORK_DIRECTORY, workDir.getAbsolutePath()); - Runner.create(properties); - assertThat(workDir.exists()).isFalse(); - } - - @Test - public void shouldCheckSonarVersion() { - Properties properties = new Properties(); - Runner runner = Runner.create(properties); - Bootstrapper bootstrapper = mock(Bootstrapper.class); - - // nothing happens, OK - when(bootstrapper.getServerVersion()).thenReturn("3.0"); - runner.checkSonarVersion(bootstrapper); - - // but fails with older versions - when(bootstrapper.getServerVersion()).thenReturn("2.1"); - thrown.expect(RunnerException.class); - thrown.expectMessage("Sonar 2.1 is not supported. Please upgrade Sonar to version 2.11 or more."); - runner.checkSonarVersion(bootstrapper); - } - - @Test - public void shouldCheckSonarVersionForTasks() { - Properties properties = new Properties(); - Runner runner = Runner.create("foo-cmd", properties, properties); - Bootstrapper bootstrapper = mock(Bootstrapper.class); - - // nothing happens, OK - when(bootstrapper.getServerVersion()).thenReturn("3.5"); - runner.checkSonarVersion(bootstrapper); - - // but fails with older versions - when(bootstrapper.getServerVersion()).thenReturn("3.4"); - thrown.expect(RunnerException.class); - thrown.expectMessage("Sonar 3.4 doesn't support tasks. Please upgrade Sonar to version 3.5 or more."); - runner.checkSonarVersion(bootstrapper); - } -} diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/api/CommandExecutorTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/api/CommandExecutorTest.java new file mode 100644 index 0000000..d63a6a3 --- /dev/null +++ b/sonar-runner-api/src/test/java/org/sonar/runner/api/CommandExecutorTest.java @@ -0,0 +1,157 @@ +/* + * 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.api; + +import org.apache.commons.io.FileUtils; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.junit.rules.TestName; + +import java.io.File; +import java.io.IOException; + +import static org.fest.assertions.Assertions.assertThat; +import static org.junit.Assert.fail; + +public class CommandExecutorTest { + + @Rule + public TemporaryFolder tempFolder = new TemporaryFolder(); + + @Rule + public TestName testName = new TestName(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private File workDir; + + @Before + public void setUp() throws IOException { + workDir = tempFolder.newFolder(testName.getMethodName()); + } + + @Test + public void should_consume_StdOut_and_StdErr() throws Exception { + final StringBuilder stdOutBuilder = new StringBuilder(); + CommandExecutor.StreamConsumer stdOutConsumer = new CommandExecutor.StreamConsumer() { + public void consumeLine(String line) { + stdOutBuilder.append(line).append(System.getProperty("line.separator")); + } + }; + final StringBuilder stdErrBuilder = new StringBuilder(); + CommandExecutor.StreamConsumer stdErrConsumer = new CommandExecutor.StreamConsumer() { + public void consumeLine(String line) { + stdErrBuilder.append(line).append(System.getProperty("line.separator")); + } + }; + Command command = Command.builder().setExecutable(getScript("output")).setDirectory(workDir).build(); + int exitCode = CommandExecutor.create().execute(command, stdOutConsumer, stdErrConsumer, 1000L); + assertThat(exitCode).isEqualTo(0); + + String stdOut = stdOutBuilder.toString(); + String stdErr = stdErrBuilder.toString(); + assertThat(stdOut).contains("stdOut: first line"); + assertThat(stdOut).contains("stdOut: second line"); + assertThat(stdErr).contains("stdErr: first line"); + assertThat(stdErr).contains("stdErr: second line"); + } + + @Test + public void stdOut_consumer_can_throw_exception() throws Exception { + Command command = Command.builder().setExecutable(getScript("output")).setDirectory(workDir).build(); + thrown.expect(CommandException.class); + thrown.expectMessage("Error inside stdOut stream"); + CommandExecutor.create().execute(command, BAD_CONSUMER, NOP_CONSUMER, 1000L); + } + + @Test + public void stdErr_consumer_can_throw_exception() throws Exception { + Command command = Command.builder().setExecutable(getScript("output")).setDirectory(workDir).build(); + thrown.expect(CommandException.class); + thrown.expectMessage("Error inside stdErr stream"); + CommandExecutor.create().execute(command, NOP_CONSUMER, BAD_CONSUMER, 1000L); + } + + private static final CommandExecutor.StreamConsumer NOP_CONSUMER = new CommandExecutor.StreamConsumer() { + public void consumeLine(String line) { + // nop + } + }; + + private static final CommandExecutor.StreamConsumer BAD_CONSUMER = new CommandExecutor.StreamConsumer() { + public void consumeLine(String line) { + throw new RuntimeException(); + } + }; + + @Test + public void should_use_working_directory_to_store_argument_and_environment_variable() throws Exception { + Command command = Command.builder() + .setDirectory(workDir) + .setExecutable(getScript("echo")) + .addArguments("1") + .setEnvVariable("ENVVAR", "2") + .build(); + int exitCode = CommandExecutor.create().execute(command, 1000L); + assertThat(exitCode).isEqualTo(0); + File logFile = new File(workDir, "echo.log"); + assertThat(logFile).exists(); + String log = FileUtils.readFileToString(logFile); + assertThat(log).contains(workDir.getAbsolutePath()); + assertThat(log).contains("Parameter: 1"); + assertThat(log).contains("Environment variable: 2"); + } + + @Test + public void should_stop_after_timeout() throws IOException { + String executable = getScript("forever"); + long start = System.currentTimeMillis(); + try { + CommandExecutor.create().execute(Command.builder().setExecutable(executable).setDirectory(workDir).build(), 300L); + fail(); + } catch (CommandException e) { + long duration = System.currentTimeMillis() - start; + // should test >= 300 but it strangly fails during build on windows. + // The timeout is raised after 297ms (??) + assertThat(duration).as(e.getMessage()).isGreaterThan(290L); + } + } + + @Test + public void should_fail_if_script_not_found() { + thrown.expect(CommandException.class); + CommandExecutor.create().execute(Command.builder().setExecutable("notfound").setDirectory(workDir).build(), 1000L); + } + + private static String getScript(String name) throws IOException { + String filename; + if (new Os().isWindows()) { + filename = name + ".bat"; + } else { + filename = name + ".sh"; + } + return new File("src/test/scripts/" + filename).getCanonicalPath(); + } + +} diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/api/CommandTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/api/CommandTest.java new file mode 100644 index 0000000..259d1c6 --- /dev/null +++ b/sonar-runner-api/src/test/java/org/sonar/runner/api/CommandTest.java @@ -0,0 +1,75 @@ +/* + * 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.api; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.fest.assertions.Assertions.assertThat; +import static org.fest.assertions.Fail.fail; +import static org.fest.assertions.MapAssert.entry; + +public class CommandTest { + @Test + public void test_simple_build() throws Exception { + Command command = Command.builder().setExecutable("java").build(); + assertThat(command.executable()).isEqualTo("java"); + assertThat(command.envVariables()).isEmpty(); + assertThat(command.arguments()).isEmpty(); + assertThat(command.toStrings()).containsOnly("java"); + assertThat(command.toString()).isEqualTo("java"); + } + + @Test + public void test_arguments_and_env_variables() throws Exception { + Map<String, String> env = new HashMap<String, String>(); + env.put("USER_HOME", "/user"); + + Command command = Command.builder() + .setExecutable("java") + .addArguments("-Dfoo=bar", "-Djava.io.tmpdir=/tmp") + .addArguments(Arrays.asList("-Xmx512m")) + .setEnvVariable("JAVA_HOME", "/path/to/jdk") + .addEnvVariables(env) + .build(); + + assertThat(command.executable()).isEqualTo("java"); + assertThat(command.envVariables()).hasSize(2).includes( + entry("JAVA_HOME", "/path/to/jdk"), + entry("USER_HOME", "/user") + ); + assertThat(command.arguments()).containsSequence("-Dfoo=bar", "-Djava.io.tmpdir=/tmp", "-Xmx512m"); + assertThat(command.toStrings()).containsOnly("java", "-Dfoo=bar", "-Djava.io.tmpdir=/tmp", "-Xmx512m"); + assertThat(command.toString()).isEqualTo("java -Dfoo=bar -Djava.io.tmpdir=/tmp -Xmx512m"); + } + + @Test + public void executable_should_be_required() { + try { + Command.builder().build(); + fail(); + } catch (IllegalArgumentException e) { + // success + } + } +} diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/api/EmbeddedRunnerTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/api/EmbeddedRunnerTest.java new file mode 100644 index 0000000..d3d2ca2 --- /dev/null +++ b/sonar-runner-api/src/test/java/org/sonar/runner/api/EmbeddedRunnerTest.java @@ -0,0 +1,54 @@ +/* + * 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.api; + +import org.junit.Test; +import org.sonar.runner.impl.Constants; + +import static org.fest.assertions.Assertions.assertThat; + +public class EmbeddedRunnerTest { + @Test + public void should_create() { + assertThat(EmbeddedRunner.create()).isNotNull().isInstanceOf(EmbeddedRunner.class); + } + + @Test + public void should_set_unmasked_packages() { + EmbeddedRunner runner = EmbeddedRunner.create(); + assertThat(runner.property(Constants.UNMASKED_PACKAGES, null)).isNull(); + + runner = EmbeddedRunner.create().setUnmaskedPackages("org.apache.ant", "org.ant"); + assertThat(runner.property(Constants.UNMASKED_PACKAGES, null)).isEqualTo("org.apache.ant,org.ant"); + } + + @Test + public void should_add_extensions() { + EmbeddedRunner runner = EmbeddedRunner.create(); + assertThat(runner.extensions()).isEmpty(); + + FakeExtension fakeExtension = new FakeExtension(); + runner.addExtensions(fakeExtension); + assertThat(runner.extensions()).containsExactly(fakeExtension); + } + + static class FakeExtension { + } +} diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/StatsTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/api/ForkedRunnerTest.java index 7ea5d84..5c8767b 100644 --- a/sonar-runner-api/src/test/java/org/sonar/runner/StatsTest.java +++ b/sonar-runner-api/src/test/java/org/sonar/runner/api/ForkedRunnerTest.java @@ -17,26 +17,15 @@ * 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; +package org.sonar.runner.api; import org.junit.Test; import static org.fest.assertions.Assertions.assertThat; - -public class StatsTest { - - @Test - public void shouldPrintStats() { - new Stats().start().stop(); - //TODO mock Logs - } - +public class ForkedRunnerTest { @Test - public void shouldFormatTime() { - assertThat(Stats.formatTime(1 * 60 * 60 * 1000 + 2 * 60 * 1000 + 3 * 1000 + 400)).isEqualTo("1:02:03.400s"); - assertThat(Stats.formatTime(2 * 60 * 1000 + 3 * 1000 + 400)).isEqualTo("2:03.400s"); - assertThat(Stats.formatTime(3 * 1000 + 400)).isEqualTo("3.400s"); - assertThat(Stats.formatTime(400)).isEqualTo("0.400s"); + public void should_create() { + assertThat(ForkedRunner.create()).isNotNull().isInstanceOf(ForkedRunner.class); } } diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/api/OsTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/api/OsTest.java new file mode 100644 index 0000000..20c4a91 --- /dev/null +++ b/sonar-runner-api/src/test/java/org/sonar/runner/api/OsTest.java @@ -0,0 +1,47 @@ +/* + * 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.api; + +import org.apache.commons.lang.SystemUtils; +import org.junit.Test; + +import java.io.File; + +import static org.fest.assertions.Assertions.assertThat; + +public class OsTest { + @Test + public void testIsWindows() throws Exception { + assertThat(new Os().isWindows()).isEqualTo(SystemUtils.IS_OS_WINDOWS); + } + + @Test + public void testUsedJavaHome() throws Exception { + File javaHome = new Os().usedJavaHome(); + assertThat(javaHome).isNotNull().exists().isDirectory(); + } + + @Test + public void testUsedJavaExe() throws Exception { + File javaExe = new Os().usedJavaExe(); + assertThat(javaExe).isNotNull().isFile().exists(); + assertThat(javaExe.getName()).contains("java"); + } +} diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/VersionTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/api/RunnerVersionTest.java index 2280195..65d13c5 100644 --- a/sonar-runner-api/src/test/java/org/sonar/runner/VersionTest.java +++ b/sonar-runner-api/src/test/java/org/sonar/runner/api/RunnerVersionTest.java @@ -17,20 +17,18 @@ * 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; +package org.sonar.runner.api; import org.junit.Test; -import org.sonar.runner.Version; import static org.fest.assertions.Assertions.assertThat; -public class VersionTest { +public class RunnerVersionTest { @Test - public void shouldLoadVersion() { - String version = Version.getVersion(); - assertThat(version).contains("."); - assertThat(version).doesNotContain("$"); + public void should_load_version() { + String version = RunnerVersion.version(); + assertThat(version).isNotEmpty().contains(".").endsWith("-SNAPSHOT").doesNotContain("$"); } } diff --git a/sonar-runner-api/src/test/java/org/sonar/runner/api/UtilsTest.java b/sonar-runner-api/src/test/java/org/sonar/runner/api/UtilsTest.java new file mode 100644 index 0000000..f956c75 --- /dev/null +++ b/sonar-runner-api/src/test/java/org/sonar/runner/api/UtilsTest.java @@ -0,0 +1,33 @@ +/* + * 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.api; + +import org.junit.Test; + +import static org.fest.assertions.Assertions.assertThat; + +public class UtilsTest { + @Test + public void should_join_strings() { + assertThat(Utils.join(new String[]{}, ",")).isEqualTo(""); + assertThat(Utils.join(new String[]{"foo"}, ",")).isEqualTo("foo"); + assertThat(Utils.join(new String[]{"foo", "bar"}, ",")).isEqualTo("foo,bar"); + } +} diff --git a/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadCompleteConfiguration/project/sonar-project.properties b/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadCompleteConfiguration/project/sonar-project.properties deleted file mode 100644 index 0d1e025..0000000 --- a/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadCompleteConfiguration/project/sonar-project.properties +++ /dev/null @@ -1,4 +0,0 @@ -project.prop=foo - -# overridden property -overridden.prop=project scope
\ No newline at end of file diff --git a/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadCompleteConfiguration/runner/conf/sonar-runner.properties b/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadCompleteConfiguration/runner/conf/sonar-runner.properties deleted file mode 100644 index 7edfb99..0000000 --- a/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadCompleteConfiguration/runner/conf/sonar-runner.properties +++ /dev/null @@ -1,2 +0,0 @@ -overridden.prop=runner scope -global.prop=jdbc:mysql:localhost/sonar diff --git a/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadRunnerSettingsByDirectPath/other-conf.properties b/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadRunnerSettingsByDirectPath/other-conf.properties deleted file mode 100644 index 740a616..0000000 --- a/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadRunnerSettingsByDirectPath/other-conf.properties +++ /dev/null @@ -1 +0,0 @@ -sonar.host.url=http://other/sonar
\ No newline at end of file diff --git a/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadRunnerSettingsByHome/conf/sonar-runner.properties b/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadRunnerSettingsByHome/conf/sonar-runner.properties deleted file mode 100644 index e7d5c09..0000000 --- a/sonar-runner-api/src/test/resources/org/sonar/runner/MainTest/shouldLoadRunnerSettingsByHome/conf/sonar-runner.properties +++ /dev/null @@ -1,2 +0,0 @@ -sonar.host.url=http://moon/sonar -sonar.jdbc.url=jdbc:mysql:localhost/sonar
\ No newline at end of file diff --git a/sonar-runner-api/src/test/resources/org/sonar/runner/RunnerTest/shouldInitDirs/fake.txt b/sonar-runner-api/src/test/resources/org/sonar/runner/RunnerTest/shouldInitDirs/fake.txt deleted file mode 100644 index f0f877c..0000000 --- a/sonar-runner-api/src/test/resources/org/sonar/runner/RunnerTest/shouldInitDirs/fake.txt +++ /dev/null @@ -1 +0,0 @@ -fake
\ No newline at end of file diff --git a/sonar-runner-api/src/test/scripts/echo.bat b/sonar-runner-api/src/test/scripts/echo.bat new file mode 100755 index 0000000..6622b99 --- /dev/null +++ b/sonar-runner-api/src/test/scripts/echo.bat @@ -0,0 +1,4 @@ +@ECHO OFF +@ECHO %CD% > echo.log +@ECHO Parameter: %1 >> echo.log +@ECHO Environment variable: %ENVVAR% >> echo.log diff --git a/sonar-runner-api/src/test/scripts/echo.sh b/sonar-runner-api/src/test/scripts/echo.sh new file mode 100755 index 0000000..8931fd8 --- /dev/null +++ b/sonar-runner-api/src/test/scripts/echo.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +WORKING_DIR=`pwd` +echo $WORKING_DIR > echo.log +echo "Parameter: $1" >> echo.log +echo "Environment variable: $ENVVAR" >> echo.log diff --git a/sonar-runner-api/src/test/scripts/forever.bat b/sonar-runner-api/src/test/scripts/forever.bat new file mode 100755 index 0000000..a7d9218 --- /dev/null +++ b/sonar-runner-api/src/test/scripts/forever.bat @@ -0,0 +1,6 @@ +@ECHO OFF + +:LOOP + @rem Next line may lead to freeze of build process on Windows 7 due to non-terminated ping-processes + @rem ping 1.1.1.1 -n 2 -w 60000 > nul +GOTO LOOP diff --git a/sonar-runner-api/src/test/scripts/forever.sh b/sonar-runner-api/src/test/scripts/forever.sh new file mode 100755 index 0000000..d7b6a9b --- /dev/null +++ b/sonar-runner-api/src/test/scripts/forever.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +while test "notempty" +do + sleep 1 +done diff --git a/sonar-runner-api/src/test/scripts/output.bat b/sonar-runner-api/src/test/scripts/output.bat new file mode 100755 index 0000000..967bc60 --- /dev/null +++ b/sonar-runner-api/src/test/scripts/output.bat @@ -0,0 +1,5 @@ +@ECHO OFF +@ECHO stdOut: first line +@ECHO stdOut: second line +@ECHO stdErr: first line 1>&2 +@ECHO stdErr: second line 1>&2 diff --git a/sonar-runner-api/src/test/scripts/output.sh b/sonar-runner-api/src/test/scripts/output.sh new file mode 100755 index 0000000..cbb0fea --- /dev/null +++ b/sonar-runner-api/src/test/scripts/output.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +echo stdOut: first line +echo stdOut: second line +echo stdErr: first line 1>&2 +echo stdErr: second line 1>&2 |