diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2017-02-23 18:32:30 +0100 |
---|---|---|
committer | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2017-02-24 21:14:15 +0100 |
commit | 132100250bc9dabdb0e28944e7d2f0e8629c6102 (patch) | |
tree | 08e608fa390d33e3fb9a55f7ebd92fe74d9ef45c /sonar-application/src/main/java | |
parent | cfe7a59ac8d45c4d1d7def3923c67c5b48f70161 (diff) | |
download | sonarqube-132100250bc9dabdb0e28944e7d2f0e8629c6102.tar.gz sonarqube-132100250bc9dabdb0e28944e7d2f0e8629c6102.zip |
SONAR-7937 restart reloads sonar.properties
but changes of FileSystem related properties are not supported and will make restart fail
Diffstat (limited to 'sonar-application/src/main/java')
-rw-r--r-- | sonar-application/src/main/java/org/sonar/application/App.java | 88 | ||||
-rw-r--r-- | sonar-application/src/main/java/org/sonar/application/AppFileSystem.java | 19 |
2 files changed, 89 insertions, 18 deletions
diff --git a/sonar-application/src/main/java/org/sonar/application/App.java b/sonar-application/src/main/java/org/sonar/application/App.java index d6c3b843a85..8fc3ba6f5b3 100644 --- a/sonar-application/src/main/java/org/sonar/application/App.java +++ b/sonar-application/src/main/java/org/sonar/application/App.java @@ -19,10 +19,14 @@ */ package org.sonar.application; +import com.google.common.annotations.VisibleForTesting; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Properties; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; import org.apache.commons.io.FilenameUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -41,27 +45,46 @@ import static org.sonar.process.ProcessId.APP; */ public class App implements Stoppable { + private final Properties commandLineArguments; + private final Function<Properties, Props> propsSupplier; private final JavaCommandFactory javaCommandFactory; private final Monitor monitor; + private final Supplier<List<JavaCommand>> javaCommandSupplier; - public App(AppFileSystem appFileSystem, boolean watchForHardStop) { - this(Monitor.newMonitorBuilder() + private App(Properties commandLineArguments) { + this.commandLineArguments = commandLineArguments; + this.propsSupplier = properties -> new PropsBuilder(properties, new JdbcSettings()).build(); + this.javaCommandFactory = new JavaCommandFactoryImpl(); + Props props = propsSupplier.apply(commandLineArguments); + + AppFileSystem appFileSystem = new AppFileSystem(props); + appFileSystem.verifyProps(); + AppLogging logging = new AppLogging(); + logging.configure(props); + + // used by orchestrator + boolean watchForHardStop = props.valueAsBoolean(ProcessProperties.ENABLE_STOP_COMMAND, false); + this.monitor = Monitor.newMonitorBuilder() .setProcessNumber(APP.getIpcIndex()) .setFileSystem(appFileSystem) .setWatchForHardStop(watchForHardStop) .setWaitForOperational() .addListener(new AppLifecycleListener()) - .build(), - new JavaCommandFactoryImpl()); + .build(); + this.javaCommandSupplier = new ReloadableCommandSupplier(props, appFileSystem::ensureUnchangedConfiguration); } - App(Monitor monitor, JavaCommandFactory javaCommandFactory) { + @VisibleForTesting + App(Properties commandLineArguments, Function<Properties, Props> propsSupplier, Monitor monitor, CheckFSConfigOnReload checkFsConfigOnReload, JavaCommandFactory javaCommandFactory) { + this.commandLineArguments = commandLineArguments; + this.propsSupplier = propsSupplier; this.javaCommandFactory = javaCommandFactory; this.monitor = monitor; + this.javaCommandSupplier = new ReloadableCommandSupplier(propsSupplier.apply(commandLineArguments), checkFsConfigOnReload); } - public void start(Props props) throws InterruptedException { - monitor.start(() -> createCommands(props)); + public void start() throws InterruptedException { + monitor.start(javaCommandSupplier); monitor.awaitTermination(); } @@ -96,21 +119,16 @@ public class App implements Stoppable { public static void main(String[] args) throws InterruptedException { CommandLineParser cli = new CommandLineParser(); Properties rawProperties = cli.parseArguments(args); - Props props = new PropsBuilder(rawProperties, new JdbcSettings()).build(); - AppFileSystem appFileSystem = new AppFileSystem(props); - appFileSystem.verifyProps(); - AppLogging logging = new AppLogging(); - logging.configure(props); - // used by orchestrator - boolean watchForHardStop = props.valueAsBoolean(ProcessProperties.ENABLE_STOP_COMMAND, false); - App app = new App(appFileSystem, watchForHardStop); - app.start(props); + App app = new App(rawProperties); + app.start(); } @Override public void stopAsync() { - monitor.stop(); + if (monitor != null) { + monitor.stop(); + } } private static class AppLifecycleListener implements Lifecycle.LifecycleListener { @@ -123,4 +141,40 @@ public class App implements Stoppable { } } } + + @FunctionalInterface + interface CheckFSConfigOnReload extends Consumer<Props> { + + } + + private class ReloadableCommandSupplier implements Supplier<List<JavaCommand>> { + private final Props initialProps; + private final CheckFSConfigOnReload checkFsConfigOnReload; + private boolean initialPropsConsumed = false; + + ReloadableCommandSupplier(Props initialProps, CheckFSConfigOnReload checkFsConfigOnReload) { + this.initialProps = initialProps; + this.checkFsConfigOnReload = checkFsConfigOnReload; + } + + @Override + public List<JavaCommand> get() { + if (!initialPropsConsumed) { + initialPropsConsumed = true; + return createCommands(this.initialProps); + } + return recreateCommands(); + } + + private List<JavaCommand> recreateCommands() { + Props reloadedProps = propsSupplier.apply(commandLineArguments); + AppFileSystem appFileSystem = new AppFileSystem(reloadedProps); + appFileSystem.verifyProps(); + checkFsConfigOnReload.accept(reloadedProps); + AppLogging logging = new AppLogging(); + logging.configure(reloadedProps); + + return createCommands(reloadedProps); + } + } } diff --git a/sonar-application/src/main/java/org/sonar/application/AppFileSystem.java b/sonar-application/src/main/java/org/sonar/application/AppFileSystem.java index d8b0497d504..9b07583314e 100644 --- a/sonar-application/src/main/java/org/sonar/application/AppFileSystem.java +++ b/sonar-application/src/main/java/org/sonar/application/AppFileSystem.java @@ -29,12 +29,14 @@ import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.EnumSet; +import java.util.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.process.AllProcessesCommands; import org.sonar.process.Props; import org.sonar.process.monitor.FileSystem; +import static java.lang.String.format; import static java.nio.file.FileVisitResult.CONTINUE; import static org.apache.commons.io.FileUtils.forceMkdir; import static org.sonar.process.FileUtils.deleteDirectory; @@ -118,7 +120,7 @@ public class AppFileSystem implements FileSystem { private static void ensureIsNotAFile(String propKey, File dir) { if (!dir.isDirectory()) { - throw new IllegalStateException(String.format("Property '%s' is not valid, not a directory: %s", + throw new IllegalStateException(format("Property '%s' is not valid, not a directory: %s", propKey, dir.getAbsolutePath())); } } @@ -132,6 +134,21 @@ public class AppFileSystem implements FileSystem { return dir; } + public void ensureUnchangedConfiguration(Props newProps) { + verifyUnchanged(newProps, PATH_DATA, DEFAULT_DATA_DIRECTORY_NAME); + verifyUnchanged(newProps, PATH_WEB, DEFAULT_WEB_DIRECTORY_NAME); + verifyUnchanged(newProps, PATH_LOGS, DEFAULT_LOGS_DIRECTORY_NAME); + verifyUnchanged(newProps, PATH_TEMP, DEFAULT_TEMP_DIRECTORY_NAME); + } + + private void verifyUnchanged(Props newProps, String propKey, String defaultRelativePath) { + String initialValue = props.value(propKey, defaultRelativePath); + String newValue = newProps.value(propKey, defaultRelativePath); + if (!Objects.equals(newValue, initialValue)) { + throw new IllegalStateException(format("Change of property '%s' is not supported ('%s'=> '%s')", propKey, initialValue, newValue)); + } + } + private static class CleanTempDirFileVisitor extends SimpleFileVisitor<Path> { private static final Path SHAREDMEMORY_FILE = Paths.get("sharedmemory"); public static final int VISIT_MAX_DEPTH = 1; |