diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2013-01-30 10:19:34 +0100 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2013-01-30 10:19:34 +0100 |
commit | 9f2628c20da0a377f81bdeffdec77691568e23c6 (patch) | |
tree | 743a4527737deeb837fe94afd336d6c8798c6935 /src/main/java | |
parent | 6c62a2c27cc29c9a74a833f2226adbd734c132ff (diff) | |
download | sonar-scanner-cli-9f2628c20da0a377f81bdeffdec77691568e23c6.tar.gz sonar-scanner-cli-9f2628c20da0a377f81bdeffdec77691568e23c6.zip |
SONAR-2291 Implemented cache on Sonar Runner side (for bootstrap JARs).
Diffstat (limited to 'src/main/java')
-rw-r--r-- | src/main/java/org/sonar/runner/BootstrapClassLoader.java | 124 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/Bootstrapper.java | 186 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/IOUtils.java | 200 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/Logs.java | 40 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/Main.java | 337 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/Runner.java | 368 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/RunnerException.java | 52 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/Stats.java | 60 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/Version.java | 52 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/internal/batch/Launcher.java | 157 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/internal/batch/SonarProjectBuilder.java | 546 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/internal/batch/SonarRunnerUtils.java | 45 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/internal/batch/package-info.java | 24 | ||||
-rw-r--r-- | src/main/java/org/sonar/runner/package-info.java | 23 |
14 files changed, 0 insertions, 2214 deletions
diff --git a/src/main/java/org/sonar/runner/BootstrapClassLoader.java b/src/main/java/org/sonar/runner/BootstrapClassLoader.java deleted file mode 100644 index 1a492c1..0000000 --- a/src/main/java/org/sonar/runner/BootstrapClassLoader.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Sonar Runner - * 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/src/main/java/org/sonar/runner/Bootstrapper.java b/src/main/java/org/sonar/runner/Bootstrapper.java deleted file mode 100644 index bfe6757..0000000 --- a/src/main/java/org/sonar/runner/Bootstrapper.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Sonar Runner - * 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.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; - -/** - * 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 int CONNECT_TIMEOUT_MILLISECONDS = 30000; - static final int READ_TIMEOUT_MILLISECONDS = 60000; - - private File bootDir; - private String serverUrl; - private String productToken; - private String serverVersion; - - /** - * @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) { - this.productToken = productToken; - 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; - 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); - IOUtils.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 = IOUtils.getCharsetFromContentType(conn.getContentType()); - if (charset == null || "".equals(charset)) { - charset = "UTF-8"; - } - Reader reader = new InputStreamReader((InputStream) conn.getContent(), 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>(); - String libs = remoteContent(BATCH_PATH); - for (String lib : libs.split(",")) { - File file = new File(bootDir, lib); - remoteContentToFile(BATCH_PATH + lib, file); - files.add(file); - } - return files; - } catch (Exception e) { - throw new IllegalStateException("Fail to download libraries from server", e); - } - } -} diff --git a/src/main/java/org/sonar/runner/IOUtils.java b/src/main/java/org/sonar/runner/IOUtils.java deleted file mode 100644 index 248d18d..0000000 --- a/src/main/java/org/sonar/runner/IOUtils.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Sonar Runner - * 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.Closeable; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.StringWriter; -import java.io.Writer; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Internal class used only by the Runner as we don't want it to depend on third-party libs. - * This class should not be used by Sonar Runner consumers. - */ -final class IOUtils { - - private IOUtils() { - // only static methods - } - - /** - * The default buffer size to use. - */ - private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; - - private static final Pattern CHARSET_PATTERN = Pattern.compile("(?i)\\bcharset=\\s*\"?([^\\s;\"]*)"); - - /** - * Unconditionally close a <code>Closeable</code>. - */ - static void closeQuietly(Closeable closeable) { - try { - if (closeable != null) { - closeable.close(); - } - } catch (IOException ioe) { - } - } - - /** - * Get the contents of a <code>Reader</code> as a String. - */ - static String toString(Reader input) throws IOException { - StringWriter sw = new StringWriter(); - copyLarge(input, sw); - return sw.toString(); - } - - /** - * Copy bytes from an <code>InputStream</code> to an <code>OutputStream</code>. - */ - static long copyLarge(InputStream input, OutputStream output) throws IOException { - byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; - long count = 0; - int n = 0; - while (-1 != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; - } - return count; - } - - /** - * Copy chars from a <code>Reader</code> to a <code>Writer</code>. - */ - static long copyLarge(Reader input, Writer output) throws IOException { - char[] buffer = new char[DEFAULT_BUFFER_SIZE]; - long count = 0; - int n = 0; - while (-1 != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; - } - return count; - } - - /** - * Duplicated from Commons IO - */ - static boolean deleteQuietly(File file) { - if (file == null) { - return false; - } - try { - if (file.isDirectory()) { - cleanDirectory(file); - } - } catch (Exception ignored) { - } - - try { - return file.delete(); - } catch (Exception ignored) { - return false; - } - } - - private static void cleanDirectory(File directory) throws IOException { - if (!directory.exists()) { - String message = directory + " does not exist"; - throw new IllegalArgumentException(message); - } - - if (!directory.isDirectory()) { - String message = directory + " is not a directory"; - throw new IllegalArgumentException(message); - } - - File[] files = directory.listFiles(); - // null if security restricted - if (files == null) { - throw new IOException("Failed to list contents of " + directory); - } - - IOException exception = null; - for (File file : files) { - try { - forceDelete(file); - } catch (IOException ioe) { - exception = ioe; - } - } - - if (null != exception) { - throw exception; - } - } - - private static void forceDelete(File file) throws IOException { - if (file.isDirectory()) { - deleteDirectory(file); - } else { - boolean filePresent = file.exists(); - if (!file.delete()) { - if (!filePresent) { - throw new FileNotFoundException("File does not exist: " + file); - } - String message = - "Unable to delete file: " + file; - throw new IOException(message); - } - } - } - - private static void deleteDirectory(File directory) throws IOException { - if (!directory.exists()) { - return; - } - - cleanDirectory(directory); - - if (!directory.delete()) { - String message = - "Unable to delete directory " + directory + "."; - throw new IOException(message); - } - } - - /** - * 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/src/main/java/org/sonar/runner/Logs.java b/src/main/java/org/sonar/runner/Logs.java deleted file mode 100644 index 2bd24d6..0000000 --- a/src/main/java/org/sonar/runner/Logs.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Sonar Runner - * 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; - -final class Logs { - private Logs() { - } - - static void info(String message) { - System.out.println("INFO: " + message); - } - - static void error(String message) { - System.err.println("ERROR: " + message); - } - - static void error(String message, Throwable t) { - System.err.println("ERROR: " + message); - if (t != null) { - t.printStackTrace(System.err); - } - } -} diff --git a/src/main/java/org/sonar/runner/Main.java b/src/main/java/org/sonar/runner/Main.java deleted file mode 100644 index add38bf..0000000 --- a/src/main/java/org/sonar/runner/Main.java +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Sonar Runner - * 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 com.google.common.annotations.VisibleForTesting; - -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"; - - @VisibleForTesting - boolean debugMode = false; - @VisibleForTesting - boolean displayVersionOnly = false; - @VisibleForTesting - boolean displayStackTrace = false; - @VisibleForTesting - String command; - @VisibleForTesting - Properties globalProperties; - @VisibleForTesting - Properties projectProperties; - - /** - * Entry point of the program. - */ - public static void main(String[] args) { - new Main().execute(args); - } - - @VisibleForTesting - 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)" : "")); - if (debugMode) { - Logs.info("Other system properties:"); - Logs.info(" - sun.arch.data.model: \"" + System.getProperty("sun.arch.data.model") + "\""); - } - Logs.info("Server: " + runner.getSonarServerURL()); - try { - Logs.info("Work directory: " + runner.getWorkDir().getCanonicalPath()); - } catch (IOException e) { - throw new RunnerException("Unable to display work 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."); - } - - @VisibleForTesting - void loadProperties(Properties argsProperties) { - globalProperties = loadGlobalProperties(argsProperties); - projectProperties = loadProjectProperties(argsProperties); - } - - @VisibleForTesting - 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; - } - - @VisibleForTesting - 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; - } - - @VisibleForTesting - 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); - } - } - - @VisibleForTesting - 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; - } - 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/src/main/java/org/sonar/runner/Runner.java b/src/main/java/org/sonar/runner/Runner.java deleted file mode 100644 index 9d404da..0000000 --- a/src/main/java/org/sonar/runner/Runner.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Sonar Runner - * 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 com.google.common.annotations.VisibleForTesting; - -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"; - - /** - * 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 workDir; - private String[] unmaskedPackages; - private List<Object> containerExtensions = new ArrayList<Object>(); - private Properties globalProperties; - private Properties projectProperties; - private boolean isEncodingPlatformDependant; - - 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(); - } - - /** - * 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()); - checkSonarVersion(bootstrapper); - delegateExecution(createClassLoader(bootstrapper)); - } - - public String getSonarServerURL() { - return projectProperties.getProperty("sonar.host.url", globalProperties.getProperty("sonar.host.url", "http://localhost:9000")); - } - - private void initDirs() { - String path = projectProperties.getProperty(PROPERTY_SONAR_PROJECT_BASEDIR, "."); - projectDir = new File(path); - if (!projectDir.isDirectory()) { - throw new RunnerException("Project home must be an existing directory: " + path); - } - // project home exists: add its absolute path as "sonar.projectBaseDir" property - projectProperties.put(PROPERTY_SONAR_PROJECT_BASEDIR, projectDir.getAbsolutePath()); - workDir = initWorkDir(); - } - - 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)); - } - IOUtils.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 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 - */ - @VisibleForTesting - 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) { - for (String unsupportedVersion : UNSUPPORTED_VERSIONS) { - if (isVersion(version, unsupportedVersion)) { - return true; - } - } - return false; - } - - static boolean isUnsupportedVersionForTasks(String version) { - for (String unsupportedVersion : UNSUPPORTED_VERSIONS_FOR_TASKS) { - if (isVersion(version, unsupportedVersion)) { - return true; - } - } - return false; - } - - static boolean isVersion(String version, String prefix) { - return version.startsWith(prefix + ".") || version.equals(prefix); - } - - 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/src/main/java/org/sonar/runner/RunnerException.java b/src/main/java/org/sonar/runner/RunnerException.java deleted file mode 100644 index 27ffffb..0000000 --- a/src/main/java/org/sonar/runner/RunnerException.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Sonar Runner - * 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; - -/** - * Exception thrown by the Sonar Runner when something bad happens. - * - * @since 1.2 - */ -public class RunnerException extends RuntimeException { - - private static final long serialVersionUID = 4810407777585753030L; - - /** - * See {@link RuntimeException} - */ - public RunnerException(String message) { - super(message); - } - - /** - * See {@link RuntimeException} - */ - public RunnerException(Throwable cause) { - super(cause); - } - - /** - * See {@link RuntimeException} - */ - public RunnerException(String message, Throwable cause) { - super(message, cause); - } - -} diff --git a/src/main/java/org/sonar/runner/Stats.java b/src/main/java/org/sonar/runner/Stats.java deleted file mode 100644 index fdec553..0000000 --- a/src/main/java/org/sonar/runner/Stats.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Sonar Runner - * 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/src/main/java/org/sonar/runner/Version.java b/src/main/java/org/sonar/runner/Version.java deleted file mode 100644 index 313d727..0000000 --- a/src/main/java/org/sonar/runner/Version.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Sonar Runner - * 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.io.InputStream; -import java.util.Properties; - -public enum Version { - - INSTANCE; - - private static final String PROPERTIES_PATH = "/org/sonar/runner/version.txt"; - private String version; - - public static String getVersion() { - return INSTANCE.version; - } - - private Version() { - InputStream input = getClass().getResourceAsStream(PROPERTIES_PATH); - try { - Properties properties = new Properties(); - properties.load(input); - this.version = properties.getProperty("version"); - - } catch (IOException e) { - // Can not load the version - this.version = ""; - - } finally { - IOUtils.closeQuietly(input); - } - } -} diff --git a/src/main/java/org/sonar/runner/internal/batch/Launcher.java b/src/main/java/org/sonar/runner/internal/batch/Launcher.java deleted file mode 100644 index 1aebbd9..0000000 --- a/src/main/java/org/sonar/runner/internal/batch/Launcher.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Sonar Runner - * 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.internal.batch; - -import ch.qos.logback.classic.LoggerContext; -import ch.qos.logback.classic.joran.JoranConfigurator; -import ch.qos.logback.core.joran.spi.JoranException; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Maps; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.bootstrap.ProjectDefinition; -import org.sonar.api.batch.bootstrap.ProjectReactor; -import org.sonar.api.utils.SonarException; -import org.sonar.batch.bootstrapper.Batch; -import org.sonar.batch.bootstrapper.EnvironmentInformation; -import org.sonar.runner.Runner; - -import java.io.InputStream; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -/** - * Contrary to {@link org.sonar.runner.Runner}, this class is executed within the classloader - * provided by the server. It contains the installed plugins and the same version of sonar-batch as the server. - */ -public class Launcher { - - private String command; - private Properties globalProperties; - private Properties projectProperties; - private List<Object> containerExtensions; - - /** - * @deprecated Use {@link Launcher#Launcher(String, Properties, Properties, List)} instead - */ - @Deprecated - public Launcher(Properties properties, List<Object> containerExtensions) { - this("project-analysis", new Properties(), properties, containerExtensions); - } - - public Launcher(String command, Properties globalProperties, Properties projectProperties, List<Object> containerExtensions) { - this.command = command; - this.globalProperties = globalProperties; - this.projectProperties = projectProperties; - this.containerExtensions = containerExtensions; - } - - /** - * Main entry point. - */ - public void execute() { - Properties globalConfiguration = getInitialConfiguration(); - globalConfiguration.putAll(globalProperties); - initLogging(globalConfiguration); - - Properties projectConfiguration = new Properties(); - projectConfiguration.putAll(globalConfiguration); - projectConfiguration.putAll(projectProperties); - ProjectDefinition project = SonarProjectBuilder.create(command, projectConfiguration).generateProjectDefinition(); - - executeBatch(globalConfiguration, project); - } - - private void executeBatch(Properties globalConfiguration, ProjectDefinition project) { - String envKey = globalProperties.getProperty(Runner.PROPERTY_ENVIRONMENT_INFORMATION_KEY); - String envVersion = globalProperties.getProperty(Runner.PROPERTY_ENVIRONMENT_INFORMATION_VERSION); - Batch.Builder builder = Batch.builder() - .setEnvironment(new EnvironmentInformation(envKey, envVersion)); - for (Object extension : containerExtensions) { - builder.addComponent(extension); - } - if (project != null) { - builder.setProjectReactor(new ProjectReactor(project)); - } - if (StringUtils.isNotBlank(command)) { - // This code can only works on Sonar 3.5+ - builder - .setGlobalProperties(toMap(globalConfiguration)) - .setTaskCommand(command); - } - Batch batch = builder.build(); - batch.execute(); - } - - private Map<String, String> toMap(Properties props) { - Map<String, String> result = Maps.newHashMap(); - for (Map.Entry<Object, Object> entry : props.entrySet()) { - result.put(entry.getKey().toString(), entry.getValue().toString()); - } - return result; - } - - private void initLogging(Properties props) { - LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); - JoranConfigurator jc = new JoranConfigurator(); - jc.setContext(context); - context.reset(); - InputStream input = Batch.class.getResourceAsStream("/org/sonar/batch/logback.xml"); - System.setProperty("ROOT_LOGGER_LEVEL", isDebug() ? "DEBUG" : "INFO"); - context.putProperty("SQL_LOGGER_LEVEL", getSqlLevel(props)); - context.putProperty("SQL_RESULTS_LOGGER_LEVEL", getSqlResultsLevel(props)); - try { - jc.doConfigure(input); - - } catch (JoranException e) { - throw new SonarException("can not initialize logging", e); - - } finally { - IOUtils.closeQuietly(input); - } - } - - @VisibleForTesting - protected boolean isDebug() { - return Boolean.parseBoolean(projectProperties.getProperty(Runner.PROPERTY_VERBOSE, projectProperties.getProperty(Runner.PROPERTY_OLD_DEBUG_MODE, "false"))); - } - - @VisibleForTesting - protected static String getSqlLevel(Properties props) { - boolean showSql = "true".equals(props.get("sonar.showSql")); - return showSql ? "DEBUG" : "WARN"; - } - - @VisibleForTesting - protected static String getSqlResultsLevel(Properties props) { - boolean showSql = "true".equals(props.get("sonar.showSqlResults")); - return showSql ? "DEBUG" : "WARN"; - } - - private Properties getInitialConfiguration() { - Properties props = new Properties(); - props.putAll(System.getProperties()); - props.putAll(System.getenv()); - return props; - } - -} diff --git a/src/main/java/org/sonar/runner/internal/batch/SonarProjectBuilder.java b/src/main/java/org/sonar/runner/internal/batch/SonarProjectBuilder.java deleted file mode 100644 index 84b8788..0000000 --- a/src/main/java/org/sonar/runner/internal/batch/SonarProjectBuilder.java +++ /dev/null @@ -1,546 +0,0 @@ -/* - * Sonar Runner - * 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.internal.batch; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import org.apache.commons.io.IOUtils; -import org.apache.commons.io.filefilter.AndFileFilter; -import org.apache.commons.io.filefilter.FileFileFilter; -import org.apache.commons.io.filefilter.WildcardFileFilter; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.batch.bootstrap.ProjectDefinition; -import org.sonar.runner.RunnerException; - -import java.io.File; -import java.io.FileFilter; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; - -/** - * Class that creates a Sonar project definition based on a set of properties. - * - * @since 1.5 - */ -public final class SonarProjectBuilder { - - private static final Logger LOG = LoggerFactory.getLogger(SonarProjectBuilder.class); - - private static final String PROPERTY_PROJECT_BASEDIR = "sonar.projectBaseDir"; - private static final String PROPERTY_PROJECT_CONFIG_FILE = "sonar.projectConfigFile"; - private static final String PROPERTY_PROJECT_KEY = "sonar.projectKey"; - private static final String PROPERTY_PROJECT_NAME = "sonar.projectName"; - private static final String PROPERTY_PROJECT_DESCRIPTION = "sonar.projectDescription"; - private static final String PROPERTY_PROJECT_VERSION = "sonar.projectVersion"; - private static final String PROPERTY_MODULES = "sonar.modules"; - - /** - * New properties, to be consistent with Sonar naming conventions - * @since 1.5 - */ - private static final String PROPERTY_SOURCES = "sonar.sources"; - private static final String PROPERTY_TESTS = "sonar.tests"; - private static final String PROPERTY_BINARIES = "sonar.binaries"; - private static final String PROPERTY_LIBRARIES = "sonar.libraries"; - - /** - * Old deprecated properties, replaced by the same ones preceded by "sonar." - */ - private static final String PROPERTY_OLD_SOURCES = "sources"; - private static final String PROPERTY_OLD_TESTS = "tests"; - private static final String PROPERTY_OLD_BINARIES = "binaries"; - private static final String PROPERTY_OLD_LIBRARIES = "libraries"; - private static final Map<String, String> DEPRECATED_PROPS_TO_NEW_PROPS = new HashMap<String, String>() { - { - put(PROPERTY_OLD_SOURCES, PROPERTY_SOURCES); - put(PROPERTY_OLD_TESTS, PROPERTY_TESTS); - put(PROPERTY_OLD_BINARIES, PROPERTY_BINARIES); - put(PROPERTY_OLD_LIBRARIES, PROPERTY_LIBRARIES); - } - }; - - /** - * @since 1.4 - */ - private static final String PROPERTY_WORK_DIRECTORY = "sonar.working.directory"; - private static final String DEF_VALUE_WORK_DIRECTORY = ".sonar"; - - /** - * Array of all mandatory properties required for a project without child. - */ - private static final String[] MANDATORY_PROPERTIES_FOR_SIMPLE_PROJECT = {PROPERTY_PROJECT_BASEDIR, PROPERTY_PROJECT_KEY, PROPERTY_PROJECT_NAME, PROPERTY_PROJECT_VERSION, - PROPERTY_SOURCES}; - - /** - * Array of all mandatory properties required for a project with children. - */ - private static final String[] MANDATORY_PROPERTIES_FOR_MULTIMODULE_PROJECT = {PROPERTY_PROJECT_BASEDIR, PROPERTY_PROJECT_KEY, PROPERTY_PROJECT_NAME, PROPERTY_PROJECT_VERSION}; - - /** - * Array of all mandatory properties required for a child project before its properties get merged with its parent ones. - */ - private static final String[] MANDATORY_PROPERTIES_FOR_CHILD = {PROPERTY_PROJECT_KEY, PROPERTY_PROJECT_NAME}; - - /** - * Properties that must not be passed from the parent project to its children. - */ - private static final List<String> NON_HERITED_PROPERTIES_FOR_CHILD = Lists.newArrayList(PROPERTY_PROJECT_BASEDIR, PROPERTY_MODULES, PROPERTY_PROJECT_DESCRIPTION); - - private String command; - private Properties properties; - private File rootProjectWorkDir; - - private SonarProjectBuilder(String command, Properties properties) { - this.command = command; - this.properties = properties; - } - - public static SonarProjectBuilder create(Properties properties) { - return create(null, properties); - } - - public static SonarProjectBuilder create(String command, Properties properties) { - return new SonarProjectBuilder(command, properties); - } - - public ProjectDefinition generateProjectDefinition() { - if (StringUtils.isBlank(command) || "inspect".equals(command)) { - ProjectDefinition rootProject = defineProject(properties, null); - rootProjectWorkDir = rootProject.getWorkDir(); - defineChildren(rootProject); - cleanAndCheckProjectDefinitions(rootProject); - return rootProject; - } - else if (properties.containsKey(PROPERTY_PROJECT_KEY)) { - return defineTaskContext(); - } - else { - return null; - } - } - - private ProjectDefinition defineTaskContext() { - File baseDir = new File(System.getProperty("user.home")); - File workDir = initRootProjectWorkDir(baseDir); - - ProjectDefinition definition = ProjectDefinition.create().setProperties(properties) - .setBaseDir(baseDir) - .setWorkDir(workDir); - return definition; - } - - private ProjectDefinition defineProject(Properties properties, ProjectDefinition parent) { - if (properties.containsKey(PROPERTY_MODULES)) { - checkMandatoryProperties(properties, MANDATORY_PROPERTIES_FOR_MULTIMODULE_PROJECT); - } - else { - checkMandatoryProperties(properties, MANDATORY_PROPERTIES_FOR_SIMPLE_PROJECT); - } - File baseDir = new File(properties.getProperty(PROPERTY_PROJECT_BASEDIR)); - File workDir = null; - if (parent == null) { - workDir = initRootProjectWorkDir(baseDir); - } else { - workDir = initModuleWorkDir(properties); - } - - ProjectDefinition definition = ProjectDefinition.create().setProperties(properties) - .setBaseDir(baseDir) - .setWorkDir(workDir); - return definition; - } - - @VisibleForTesting - protected File initRootProjectWorkDir(File baseDir) { - String workDir = properties.getProperty(PROPERTY_WORK_DIRECTORY); - if (StringUtils.isBlank(workDir)) { - return new File(baseDir, DEF_VALUE_WORK_DIRECTORY); - } - - File customWorkDir = new File(workDir); - if (customWorkDir.isAbsolute()) { - return customWorkDir; - } - return new File(baseDir, customWorkDir.getPath()); - } - - @VisibleForTesting - protected File initModuleWorkDir(Properties properties) { - String cleanKey = StringUtils.deleteWhitespace(properties.getProperty(PROPERTY_PROJECT_KEY)); - cleanKey = StringUtils.replace(cleanKey, ":", "_"); - return new File(rootProjectWorkDir, cleanKey); - } - - private void defineChildren(ProjectDefinition parentProject) { - Properties parentProps = parentProject.getProperties(); - if (parentProps.containsKey(PROPERTY_MODULES)) { - for (String module : SonarRunnerUtils.getListFromProperty(parentProps, PROPERTY_MODULES)) { - Properties moduleProps = extractModuleProperties(module, parentProps); - ProjectDefinition childProject = loadChildProject(parentProject, moduleProps, module); - // check the uniqueness of the child key - checkUniquenessOfChildKey(childProject, parentProject); - // the child project may have children as well - defineChildren(childProject); - // and finally add this child project to its parent - parentProject.addSubProject(childProject); - } - } - } - - private ProjectDefinition loadChildProject(ProjectDefinition parentProject, Properties moduleProps, String moduleId) { - setProjectKeyAndNameIfNotDefined(moduleProps, moduleId); - - final File baseDir; - if (moduleProps.containsKey(PROPERTY_PROJECT_BASEDIR)) { - baseDir = getFileFromPath(moduleProps.getProperty(PROPERTY_PROJECT_BASEDIR), parentProject.getBaseDir()); - setProjectBaseDir(baseDir, moduleProps, moduleId); - try { - if (!parentProject.getBaseDir().getCanonicalFile().equals(baseDir.getCanonicalFile())) { - tryToFindAndLoadPropsFile(baseDir, moduleProps, moduleId); - } - } catch (IOException e) { - throw new RunnerException("Error when resolving baseDir", e); - } - } else if (moduleProps.containsKey(PROPERTY_PROJECT_CONFIG_FILE)) { - baseDir = loadPropsFile(parentProject, moduleProps, moduleId); - } else { - baseDir = new File(parentProject.getBaseDir(), moduleId); - setProjectBaseDir(baseDir, moduleProps, moduleId); - tryToFindAndLoadPropsFile(baseDir, moduleProps, moduleId); - } - - // and finish - checkMandatoryProperties(moduleProps, MANDATORY_PROPERTIES_FOR_CHILD); - if (!moduleProps.containsKey(PROPERTY_MODULES)) { - // SONARPLUGINS-2285 Not an aggreator project so we can validate that paths are correct if defined - - // We need to resolve patterns that may have been used in "sonar.libraries" - for (String pattern : SonarRunnerUtils.getListFromProperty(moduleProps, PROPERTY_LIBRARIES)) { - File[] files = getLibraries(baseDir, pattern); - if (files == null || files.length == 0) { - LOG.error("Invalid value of " + PROPERTY_LIBRARIES + " for module " + moduleId); - throw new RunnerException("No files matching pattern \"" + pattern + "\" in directory \"" + baseDir + "\""); - } - } - - // Check sonar.tests - String[] testDirs = SonarRunnerUtils.getListFromProperty(moduleProps, PROPERTY_TESTS); - checkExistenceOfDirectories(moduleId, baseDir, testDirs, PROPERTY_TESTS); - - // Check sonar.binaries - String[] binDirs = SonarRunnerUtils.getListFromProperty(moduleProps, PROPERTY_BINARIES); - checkExistenceOfDirectories(moduleId, baseDir, binDirs, PROPERTY_BINARIES); - } - mergeParentProperties(moduleProps, parentProject.getProperties()); - - prefixProjectKeyWithParentKey(moduleProps, parentProject.getKey()); - - return defineProject(moduleProps, parentProject); - } - - /** - * @return baseDir - */ - protected File loadPropsFile(ProjectDefinition parentProject, Properties moduleProps, String moduleId) { - File propertyFile = getFileFromPath(moduleProps.getProperty(PROPERTY_PROJECT_CONFIG_FILE), parentProject.getBaseDir()); - if (propertyFile.isFile()) { - Properties propsFromFile = toProperties(propertyFile); - for (Entry<Object, Object> entry : propsFromFile.entrySet()) { - moduleProps.put(entry.getKey(), entry.getValue()); - } - File baseDir = null; - if (moduleProps.containsKey(PROPERTY_PROJECT_BASEDIR)) { - baseDir = getFileFromPath(moduleProps.getProperty(PROPERTY_PROJECT_BASEDIR), propertyFile.getParentFile()); - } else { - baseDir = propertyFile.getParentFile(); - } - setProjectBaseDir(baseDir, moduleProps, moduleId); - return baseDir; - } else { - throw new RunnerException("The properties file of the module '" + moduleId + "' does not exist: " + propertyFile.getAbsolutePath()); - } - } - - private void tryToFindAndLoadPropsFile(File baseDir, Properties moduleProps, String moduleId) { - File propertyFile = new File(baseDir, "sonar-project.properties"); - if (propertyFile.isFile()) { - Properties propsFromFile = toProperties(propertyFile); - for (Entry<Object, Object> entry : propsFromFile.entrySet()) { - moduleProps.put(entry.getKey(), entry.getValue()); - } - if (moduleProps.containsKey(PROPERTY_PROJECT_BASEDIR)) { - File overwrittenBaseDir = getFileFromPath(moduleProps.getProperty(PROPERTY_PROJECT_BASEDIR), propertyFile.getParentFile()); - setProjectBaseDir(overwrittenBaseDir, moduleProps, moduleId); - } - } - } - - @VisibleForTesting - protected static Properties toProperties(File propertyFile) { - Properties propsFromFile = new Properties(); - FileInputStream fileInputStream = null; - try { - fileInputStream = new FileInputStream(propertyFile); - propsFromFile.load(fileInputStream); - } catch (IOException e) { - throw new RunnerException("Impossible to read the property file: " + propertyFile.getAbsolutePath(), e); - } finally { - IOUtils.closeQuietly(fileInputStream); - } - return propsFromFile; - } - - @VisibleForTesting - protected static void setProjectKeyAndNameIfNotDefined(Properties childProps, String moduleId) { - if (!childProps.containsKey(PROPERTY_PROJECT_KEY)) { - childProps.put(PROPERTY_PROJECT_KEY, moduleId); - } - if (!childProps.containsKey(PROPERTY_PROJECT_NAME)) { - childProps.put(PROPERTY_PROJECT_NAME, moduleId); - } - } - - @VisibleForTesting - protected static void checkUniquenessOfChildKey(ProjectDefinition childProject, ProjectDefinition parentProject) { - for (ProjectDefinition definition : parentProject.getSubProjects()) { - if (definition.getKey().equals(childProject.getKey())) { - throw new RunnerException("Project '" + parentProject.getKey() + "' can't have 2 modules with the following key: " + childProject.getKey()); - } - } - } - - @VisibleForTesting - protected static void prefixProjectKeyWithParentKey(Properties childProps, String parentKey) { - String childKey = childProps.getProperty(PROPERTY_PROJECT_KEY); - childProps.put(PROPERTY_PROJECT_KEY, parentKey + ":" + childKey); - } - - private static void setProjectBaseDir(File baseDir, Properties childProps, String moduleId) { - if (!baseDir.isDirectory()) { - throw new RunnerException("The base directory of the module '" + moduleId + "' does not exist: " + baseDir.getAbsolutePath()); - } - childProps.put(PROPERTY_PROJECT_BASEDIR, baseDir.getAbsolutePath()); - } - - @VisibleForTesting - protected static void checkMandatoryProperties(Properties props, String[] mandatoryProps) { - replaceDeprecatedProperties(props); - StringBuilder missing = new StringBuilder(); - for (String mandatoryProperty : mandatoryProps) { - if (!props.containsKey(mandatoryProperty)) { - if (missing.length() > 0) { - missing.append(", "); - } - missing.append(mandatoryProperty); - } - } - if (missing.length() != 0) { - String projectKey = props.getProperty(PROPERTY_PROJECT_KEY); - throw new RunnerException("You must define the following mandatory properties for '" + (projectKey == null ? "Unknown" : projectKey) + "': " + missing); - } - } - - @VisibleForTesting - protected static void cleanAndCheckProjectDefinitions(ProjectDefinition project) { - if (project.getSubProjects().isEmpty()) { - cleanAndCheckModuleProperties(project); - } else { - cleanAndCheckAggregatorProjectProperties(project); - - // clean modules properties as well - for (ProjectDefinition module : project.getSubProjects()) { - cleanAndCheckProjectDefinitions(module); - } - } - } - - @VisibleForTesting - protected static void cleanAndCheckModuleProperties(ProjectDefinition project) { - Properties properties = project.getProperties(); - - // We need to check the existence of source directories - String[] sourceDirs = SonarRunnerUtils.getListFromProperty(properties, PROPERTY_SOURCES); - checkExistenceOfDirectories(project.getKey(), project.getBaseDir(), sourceDirs, PROPERTY_SOURCES); - - // And we need to resolve patterns that may have been used in "sonar.libraries" - List<String> libPaths = Lists.newArrayList(); - for (String pattern : SonarRunnerUtils.getListFromProperty(properties, PROPERTY_LIBRARIES)) { - for (File file : getLibraries(project.getBaseDir(), pattern)) { - libPaths.add(file.getAbsolutePath()); - } - } - properties.remove(PROPERTY_LIBRARIES); - properties.put(PROPERTY_LIBRARIES, StringUtils.join(libPaths, ",")); - } - - @VisibleForTesting - protected static void cleanAndCheckAggregatorProjectProperties(ProjectDefinition project) { - Properties properties = project.getProperties(); - - // SONARPLUGINS-2295 - String[] sourceDirs = SonarRunnerUtils.getListFromProperty(properties, PROPERTY_SOURCES); - for (String path : sourceDirs) { - File sourceFolder = getFileFromPath(path, project.getBaseDir()); - if (sourceFolder.isDirectory()) { - LOG.warn("/!\\ A multi-module project can't have source folders, so '{}' won't be used for the analysis. " + - "If you want to analyse files of this folder, you should create another sub-module and move them inside it.", - sourceFolder.toString()); - } - } - - // "aggregator" project must not have the following properties: - properties.remove(PROPERTY_SOURCES); - properties.remove(PROPERTY_TESTS); - properties.remove(PROPERTY_BINARIES); - properties.remove(PROPERTY_LIBRARIES); - - // and they don't need properties related to their modules either - Properties clone = (Properties) properties.clone(); - List<String> moduleIds = Lists.newArrayList(SonarRunnerUtils.getListFromProperty(properties, PROPERTY_MODULES)); - for (Entry<Object, Object> entry : clone.entrySet()) { - String key = (String) entry.getKey(); - if (isKeyPrefixedByModuleId(key, moduleIds)) { - properties.remove(key); - } - } - } - - /** - * Replaces the deprecated properties by the new ones, and logs a message to warn the users. - */ - @VisibleForTesting - protected static void replaceDeprecatedProperties(Properties props) { - for (Entry<String, String> entry : DEPRECATED_PROPS_TO_NEW_PROPS.entrySet()) { - String key = entry.getKey(); - if (props.containsKey(key)) { - String newKey = entry.getValue(); - LOG.warn("/!\\ The '{}' property is deprecated and is replaced by '{}'. Don't forget to update your files.", key, newKey); - String value = props.getProperty(key); - props.remove(key); - props.put(newKey, value); - } - } - - } - - @VisibleForTesting - protected static void mergeParentProperties(Properties childProps, Properties parentProps) { - List<String> moduleIds = Lists.newArrayList(SonarRunnerUtils.getListFromProperty(parentProps, PROPERTY_MODULES)); - for (Map.Entry<Object, Object> entry : parentProps.entrySet()) { - String key = (String) entry.getKey(); - if (!childProps.containsKey(key) - && !NON_HERITED_PROPERTIES_FOR_CHILD.contains(key) - && !isKeyPrefixedByModuleId(key, moduleIds)) { - childProps.put(entry.getKey(), entry.getValue()); - } - } - } - - private static boolean isKeyPrefixedByModuleId(String key, List<String> moduleIds) { - for (String moduleId : moduleIds) { - if (key.startsWith(moduleId + ".")) { - return true; - } - } - return false; - } - - @VisibleForTesting - protected static Properties extractModuleProperties(String module, Properties properties) { - Properties moduleProps = new Properties(); - String propertyPrefix = module + "."; - int prefixLength = propertyPrefix.length(); - for (Map.Entry<Object, Object> entry : properties.entrySet()) { - String key = (String) entry.getKey(); - if (key.startsWith(propertyPrefix)) { - moduleProps.put(key.substring(prefixLength), entry.getValue()); - } - } - return moduleProps; - } - - @VisibleForTesting - protected static void checkExistenceOfDirectories(String moduleRef, File baseDir, String[] sourceDirs, String propName) { - for (String path : sourceDirs) { - File sourceFolder = getFileFromPath(path, baseDir); - if (!sourceFolder.isDirectory()) { - LOG.error("Invalid value of " + propName + " for " + moduleRef); - throw new RunnerException("The folder '" + path + "' does not exist for '" + moduleRef + - "' (base directory = " + baseDir.getAbsolutePath() + ")"); - } - } - - } - - /** - * Returns files matching specified pattern. - */ - @VisibleForTesting - protected static File[] getLibraries(File baseDir, String pattern) { - final int i = Math.max(pattern.lastIndexOf('/'), pattern.lastIndexOf('\\')); - final String dirPath, filePattern; - if (i == -1) { - dirPath = "."; - filePattern = pattern; - } else { - dirPath = pattern.substring(0, i); - filePattern = pattern.substring(i + 1); - } - FileFilter fileFilter = new AndFileFilter(FileFileFilter.FILE, new WildcardFileFilter(filePattern)); - File dir = resolvePath(baseDir, dirPath); - File[] files = dir.listFiles(fileFilter); - if (files == null) { - files = new File[0]; - } - return files; - } - - private static File resolvePath(File baseDir, String path) { - File file = new File(path); - if (!file.isAbsolute()) { - try { - file = new File(baseDir, path).getCanonicalFile(); - } catch (IOException e) { - throw new RunnerException("Unable to resolve path \"" + path + "\"", e); - } - } - return file; - } - - /** - * Returns the file denoted by the given path, may this path be relative to "baseDir" or absolute. - */ - @VisibleForTesting - protected static File getFileFromPath(String path, File baseDir) { - File propertyFile = new File(path.trim()); - if (!propertyFile.isAbsolute()) { - propertyFile = new File(baseDir, propertyFile.getPath()); - } - return propertyFile; - } - -} diff --git a/src/main/java/org/sonar/runner/internal/batch/SonarRunnerUtils.java b/src/main/java/org/sonar/runner/internal/batch/SonarRunnerUtils.java deleted file mode 100644 index 64cd3b3..0000000 --- a/src/main/java/org/sonar/runner/internal/batch/SonarRunnerUtils.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Sonar Runner - * 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.internal.batch; - -import org.apache.commons.lang.StringUtils; - -import java.util.Properties; - -/** - * Public utility that can be used by consumers of the Sonar Runner. - */ -public final class SonarRunnerUtils { - - private SonarRunnerUtils() { - // only static methods - } - - /** - * Transforms a comma-separated list String property in to a array of trimmed strings. - * - * This works even if they are separated by whitespace characters (space char, EOL, ...) - * - */ - public static String[] getListFromProperty(Properties properties, String key) { - return StringUtils.stripAll(StringUtils.split(properties.getProperty(key, ""), ',')); - } - -} diff --git a/src/main/java/org/sonar/runner/internal/batch/package-info.java b/src/main/java/org/sonar/runner/internal/batch/package-info.java deleted file mode 100644 index b06feba..0000000 --- a/src/main/java/org/sonar/runner/internal/batch/package-info.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Sonar Runner - * 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 - */ -/** - * Internal package that creates the project definition and launches the analyses based on it. - * Should not be used by consumers. - */ -package org.sonar.runner.internal.batch;
\ No newline at end of file diff --git a/src/main/java/org/sonar/runner/package-info.java b/src/main/java/org/sonar/runner/package-info.java deleted file mode 100644 index 62e80e2..0000000 --- a/src/main/java/org/sonar/runner/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Sonar Runner - * 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 - */ -/** - * API package of the Sonar Runner. - */ -package org.sonar.runner;
\ No newline at end of file |