diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2015-06-15 14:59:17 +0200 |
---|---|---|
committer | Duarte Meneses <duarte.meneses@sonarsource.com> | 2015-06-18 17:26:05 +0200 |
commit | e4ba9869d57dc4dd92648b5c8406d26fcd550d46 (patch) | |
tree | 489e0e87f6b7df0a95095de50d0264ff355fa568 /sonar-runner-api/src/main | |
parent | 5b6747b46db7fef9238e3bbaf66d2822e03d0a6e (diff) | |
download | sonar-scanner-cli-e4ba9869d57dc4dd92648b5c8406d26fcd550d46.tar.gz sonar-scanner-cli-e4ba9869d57dc4dd92648b5c8406d26fcd550d46.zip |
SONARUNNER-136 and SONARUNNER-137 - Provide a new API to run several analysis with same process and an interactive mode
Diffstat (limited to 'sonar-runner-api/src/main')
8 files changed, 145 insertions, 73 deletions
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 index 999150d..d9903bf 100644 --- 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 @@ -80,7 +80,9 @@ class CommandExecutor { return exitCode; } catch (TimeoutException te) { - process.destroy(); + if (process != null) { + process.destroy(); + } throw new CommandException("Timeout exceeded: " + timeoutMilliseconds + " ms", command, te); } catch (CommandException e) { @@ -120,6 +122,7 @@ class CommandExecutor { private Future<Integer> executeProcess(ExecutorService executorService, Process process) { final Process finalProcess = process; return executorService.submit(new Callable<Integer>() { + @Override public Integer call() throws InterruptedException { return finalProcess.waitFor(); } diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/api/Dirs.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/Dirs.java index 1ed4a04..2ab4d6c 100644 --- a/sonar-runner-api/src/main/java/org/sonar/runner/api/Dirs.java +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/Dirs.java @@ -22,28 +22,32 @@ package org.sonar.runner.api; import org.sonar.runner.impl.Logs; import java.io.File; +import java.util.Properties; class Dirs { + private Dirs() { - void init(Runner<?> runner) { - boolean onProject = Utils.taskRequiresProject(runner.properties()); + } + + static void init(Properties p) { + boolean onProject = Utils.taskRequiresProject(p); if (onProject) { - initProjectDirs(runner); + initProjectDirs(p); } else { - initTaskDirs(runner); + initTaskDirs(p); } } - private void initProjectDirs(Runner<?> runner) { - String path = runner.property(ScanProperties.PROJECT_BASEDIR, "."); + private static void initProjectDirs(Properties p) { + String path = p.getProperty(ScanProperties.PROJECT_BASEDIR, "."); File projectDir = new File(path); if (!projectDir.isDirectory()) { throw new IllegalStateException("Project home must be an existing directory: " + path); } - runner.setProperty(ScanProperties.PROJECT_BASEDIR, projectDir.getAbsolutePath()); + p.setProperty(ScanProperties.PROJECT_BASEDIR, projectDir.getAbsolutePath()); File workDir; - path = runner.property(RunnerProperties.WORK_DIR, ""); + path = p.getProperty(RunnerProperties.WORK_DIR, ""); if ("".equals(path.trim())) { workDir = new File(projectDir, ".sonar"); @@ -54,16 +58,16 @@ class Dirs { } } Utils.deleteQuietly(workDir); - runner.setProperty(RunnerProperties.WORK_DIR, workDir.getAbsolutePath()); + p.setProperty(RunnerProperties.WORK_DIR, workDir.getAbsolutePath()); Logs.info("Work directory: " + workDir.getAbsolutePath()); } /** * Non-scan task */ - private void initTaskDirs(Runner<?> runner) { - String path = runner.property(RunnerProperties.WORK_DIR, "."); + private static void initTaskDirs(Properties p) { + String path = p.getProperty(RunnerProperties.WORK_DIR, "."); File workDir = new File(path); - runner.setProperty(RunnerProperties.WORK_DIR, workDir.getAbsolutePath()); + p.setProperty(RunnerProperties.WORK_DIR, workDir.getAbsolutePath()); } } diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/api/EmbeddedRunner.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/EmbeddedRunner.java index b0366c3..9dfad19 100644 --- a/sonar-runner-api/src/main/java/org/sonar/runner/api/EmbeddedRunner.java +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/EmbeddedRunner.java @@ -19,11 +19,14 @@ */ package org.sonar.runner.api; -import org.sonar.runner.impl.BatchLauncher; +import org.sonar.runner.batch.IsolatedLauncher; +import org.sonar.runner.impl.IsolatedLauncherFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.Properties; /** * Implementation of {@link Runner} that is executed in the same JVM. The application can inject @@ -34,19 +37,20 @@ import java.util.List; */ public class EmbeddedRunner extends Runner<EmbeddedRunner> { - private final BatchLauncher batchLauncher; + private final IsolatedLauncherFactory launcherFactory; + private IsolatedLauncher launcher; private final List<Object> extensions = new ArrayList<Object>(); private static final String MASK_RULES_PROP = "sonarRunner.maskRules"; - EmbeddedRunner(BatchLauncher bl) { - this.batchLauncher = bl; + EmbeddedRunner(IsolatedLauncherFactory bl) { + this.launcherFactory = bl; } /** * Create a new instance. */ public static EmbeddedRunner create() { - return new EmbeddedRunner(new BatchLauncher()); + return new EmbeddedRunner(new IsolatedLauncherFactory()); } /** @@ -69,12 +73,12 @@ public class EmbeddedRunner extends Runner<EmbeddedRunner> { } private EmbeddedRunner addMaskRule(String type, String fqcnPrefix) { - String existingRules = property(MASK_RULES_PROP, ""); + String existingRules = globalProperty(MASK_RULES_PROP, ""); if (!"".equals(existingRules)) { existingRules += ","; } existingRules += type + "|" + fqcnPrefix; - return setProperty(MASK_RULES_PROP, existingRules); + return setGlobalProperty(MASK_RULES_PROP, existingRules); } /** @@ -98,7 +102,18 @@ public class EmbeddedRunner extends Runner<EmbeddedRunner> { } @Override - protected void doExecute() { - batchLauncher.execute(properties(), extensions); + protected void doStart() { + launcher = launcherFactory.createLauncher(globalProperties()); + launcher.start(globalProperties(), extensions); + } + + @Override + protected void doStop() { + launcher.stop(); + } + + @Override + protected void doExecute(Properties analysisProperties) { + launcher.execute(analysisProperties); } } 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 index fd7dc0b..02fdae7 100644 --- 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 @@ -32,6 +32,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Properties; /** * Runner executed in a new JVM. @@ -136,17 +137,33 @@ public class ForkedRunner extends Runner<ForkedRunner> { } @Override - protected void doExecute() { - ForkCommand forkCommand = createCommand(); + protected void doExecute(Properties props) { + //merge both global and analysis-specific properties because it will be used both to start and to execute. + Properties p = new Properties(); + + p.putAll(globalProperties()); + p.putAll(props); + + ForkCommand forkCommand = createCommand(p); try { fork(forkCommand); } finally { deleteTempFiles(forkCommand); } } + + @Override + protected void doStop() { + //nothing to do + } + + @Override + protected void doStart() { + //nothing to do + } - ForkCommand createCommand() { - File propertiesFile = writeProperties(); + ForkCommand createCommand(Properties p) { + File propertiesFile = writeProperties(p); File jarFile = jarExtractor.extractToTemp("sonar-runner-impl"); if (javaExecutable == null) { javaExecutable = new Os().thisJavaExe().getAbsolutePath(); @@ -160,11 +177,11 @@ public class ForkedRunner extends Runner<ForkedRunner> { return new ForkCommand(command, jarFile, propertiesFile); } - private File writeProperties() { + File writeProperties(Properties p) { try { File file = File.createTempFile("sonar-project", ".properties"); try (OutputStream output = new FileOutputStream(file)) { - properties().store(output, "Generated by sonar-runner"); + p.store(output, "Generated by sonar-runner"); return file; } } catch (Exception e) { @@ -172,7 +189,7 @@ public class ForkedRunner extends Runner<ForkedRunner> { } } - private void deleteTempFiles(ForkCommand forkCommand) { + private static void deleteTempFiles(ForkCommand forkCommand) { Utils.deleteQuietly(forkCommand.jarFile); Utils.deleteQuietly(forkCommand.propertiesFile); } diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/api/PrintStreamConsumer.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/PrintStreamConsumer.java index 5be7d04..bab55a7 100644 --- a/sonar-runner-api/src/main/java/org/sonar/runner/api/PrintStreamConsumer.java +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/PrintStreamConsumer.java @@ -34,6 +34,7 @@ public class PrintStreamConsumer implements StreamConsumer { this.output = output; } + @Override public void consumeLine(String line) { output.println(line); } 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 index b4e06bc..081b7f7 100644 --- 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 @@ -24,8 +24,6 @@ import org.sonar.runner.impl.InternalProperties; import javax.annotation.Nullable; import java.io.File; -import java.io.FileOutputStream; -import java.io.OutputStream; import java.util.Properties; /** @@ -33,14 +31,14 @@ import java.util.Properties; */ public abstract class Runner<T extends Runner> { - private final Properties properties = new Properties(); + private final Properties globalProperties = new Properties(); protected Runner() { } - public Properties properties() { + public Properties globalProperties() { Properties clone = new Properties(); - clone.putAll(properties); + clone.putAll(globalProperties); return clone; } @@ -49,8 +47,8 @@ public abstract class Runner<T extends Runner> { * * @see #setProperty(String, String) */ - public T addProperties(Properties p) { - properties.putAll(p); + public T addGlobalProperties(Properties p) { + globalProperties.putAll(p); return (T) this; } @@ -60,65 +58,86 @@ public abstract class Runner<T extends Runner> { * @see RunnerProperties * @see ScanProperties */ - public T setProperty(String key, String value) { - properties.setProperty(key, value); + public T setGlobalProperty(String key, String value) { + globalProperties.setProperty(key, value); return (T) this; } - public String property(String key, @Nullable String defaultValue) { - return properties.getProperty(key, defaultValue); + public String globalProperty(String key, @Nullable String defaultValue) { + return globalProperties.getProperty(key, defaultValue); } /** * User-agent used in the HTTP requests to the Sonar server */ public T setApp(String app, String version) { - setProperty(InternalProperties.RUNNER_APP, app); - setProperty(InternalProperties.RUNNER_APP_VERSION, version); + setGlobalProperty(InternalProperties.RUNNER_APP, app); + setGlobalProperty(InternalProperties.RUNNER_APP_VERSION, version); return (T) this; } public String app() { - return property(InternalProperties.RUNNER_APP, null); + return globalProperty(InternalProperties.RUNNER_APP, null); } public String appVersion() { - return property(InternalProperties.RUNNER_APP_VERSION, null); + return globalProperty(InternalProperties.RUNNER_APP_VERSION, null); } - public void execute() { - initDefaultValues(); - new SourceEncoding().init(this); - new Dirs().init(this); - String dumpToFile = properties.getProperty(InternalProperties.RUNNER_DUMP_TO_FILE); + public void runAnalysis(Properties analysisProperties) { + Properties copy = new Properties(); + copy.putAll(analysisProperties); + initAnalysisProperties(copy); + + String dumpToFile = copy.getProperty(InternalProperties.RUNNER_DUMP_TO_FILE); if (dumpToFile != null) { File dumpFile = new File(dumpToFile); - writeProperties(dumpFile); + Utils.writeProperties(dumpFile, copy); System.out.println("Simulation mode. Configuration written to " + dumpFile.getAbsolutePath()); } else { - doExecute(); + doExecute(copy); } } - private void writeProperties(File outputFile) { - try (OutputStream output = new FileOutputStream(outputFile)) { - properties().store(output, "Generated by sonar-runner"); - } catch (Exception e) { - throw new IllegalStateException("Fail to export sonar-runner properties", e); - } + public void start() { + initGlobalDefaultValues(); + doStart(); + } + + public void stop() { + doStop(); + } + + /** + * @deprecated since 2.5 use {@link #start()}, {@link #runAnalysis(Properties)} and then {@link #stop()} + */ + @Deprecated + public final void execute() { + start(); + runAnalysis(new Properties()); + stop(); } - protected abstract void doExecute(); + protected abstract void doStart(); + + protected abstract void doStop(); + + protected abstract void doExecute(Properties analysisProperties); + + private void initGlobalDefaultValues() { + setGlobalDefaultValue(RunnerProperties.HOST_URL, "http://localhost:9000"); + setGlobalDefaultValue(InternalProperties.RUNNER_APP, "SonarQubeRunner"); + setGlobalDefaultValue(InternalProperties.RUNNER_APP_VERSION, RunnerVersion.version()); + } - private void initDefaultValues() { - setDefaultValue(RunnerProperties.HOST_URL, "http://localhost:9000"); - setDefaultValue(InternalProperties.RUNNER_APP, "SonarQubeRunner"); - setDefaultValue(InternalProperties.RUNNER_APP_VERSION, RunnerVersion.version()); + private static void initAnalysisProperties(Properties p) { + SourceEncoding.init(p); + Dirs.init(p); } - private void setDefaultValue(String key, String value) { - if (!properties.containsKey(key)) { - setProperty(key, value); + private void setGlobalDefaultValue(String key, String value) { + if (!globalProperties.containsKey(key)) { + setGlobalProperty(key, value); } } diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/api/SourceEncoding.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/SourceEncoding.java index 44d243b..0029308 100644 --- a/sonar-runner-api/src/main/java/org/sonar/runner/api/SourceEncoding.java +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/SourceEncoding.java @@ -23,21 +23,24 @@ import org.sonar.runner.impl.Logs; import java.nio.charset.Charset; import java.util.Locale; +import java.util.Properties; class SourceEncoding { - - void init(Runner<?> runner) { - boolean onProject = Utils.taskRequiresProject(runner.properties()); + private SourceEncoding() { + + } + static void init(Properties p) { + boolean onProject = Utils.taskRequiresProject(p); if (onProject) { - String sourceEncoding = runner.property(ScanProperties.PROJECT_SOURCE_ENCODING, ""); + String sourceEncoding = p.getProperty(ScanProperties.PROJECT_SOURCE_ENCODING, ""); boolean platformDependent = false; if ("".equals(sourceEncoding)) { sourceEncoding = Charset.defaultCharset().name(); platformDependent = true; - runner.setProperty(ScanProperties.PROJECT_SOURCE_ENCODING, sourceEncoding); + p.setProperty(ScanProperties.PROJECT_SOURCE_ENCODING, sourceEncoding); } Logs.info("Default locale: \"" + Locale.getDefault() + "\", source code encoding: \"" + sourceEncoding + "\"" - + (platformDependent ? " (analysis is platform dependent)" : "")); + + (platformDependent ? " (analysis is platform dependent)" : "")); } } } diff --git a/sonar-runner-api/src/main/java/org/sonar/runner/api/Utils.java b/sonar-runner-api/src/main/java/org/sonar/runner/api/Utils.java index a4286c1..4d0524a 100644 --- a/sonar-runner-api/src/main/java/org/sonar/runner/api/Utils.java +++ b/sonar-runner-api/src/main/java/org/sonar/runner/api/Utils.java @@ -23,7 +23,9 @@ import javax.annotation.Nullable; import java.io.Closeable; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; @@ -59,7 +61,15 @@ class Utils { return task == null || ScanProperties.SCAN_TASK.equals(task); } - public static void deleteQuietly(File f) { + static void writeProperties(File outputFile, Properties p) { + try (OutputStream output = new FileOutputStream(outputFile)) { + p.store(output, "Generated by sonar-runner"); + } catch (Exception e) { + throw new IllegalStateException("Fail to export sonar-runner properties", e); + } + } + + static void deleteQuietly(File f) { try { Files.walkFileTree(f.toPath(), new DeleteFileVisitor()); } catch (IOException e) { @@ -92,7 +102,7 @@ class Utils { } } - public static void closeQuietly(@Nullable Closeable c) { + static void closeQuietly(@Nullable Closeable c) { if (c == null) { return; } |