From 0c9d03f3aa048ebb6e147eb1d3fd341d0602bba7 Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Tue, 22 Jul 2014 19:59:50 +0200 Subject: [PATCH] SONAR-4898 some refactoring --- .../org/sonar/process/ProcessWrapper.java | 20 ++++---- .../java/org/sonar/search/ElasticSearch.java | 6 +-- .../platform/DefaultServerFileSystem.java | 8 ---- .../PlatformServletContextListener.java | 1 - .../sonar/server/search/IndexProperties.java | 2 +- sonar-application/pom.xml | 4 +- .../src/main/assembly/conf/sonar.properties | 6 +-- .../src/main/assembly/conf/wrapper.conf | 4 +- .../org/sonar/application/Installation.java | 48 +++++++++++++++---- .../org/sonar/application/StartServer.java | 29 +++++------ 10 files changed, 72 insertions(+), 56 deletions(-) diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessWrapper.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessWrapper.java index b909bfe550a..435c84ca355 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/ProcessWrapper.java +++ b/server/sonar-process/src/main/java/org/sonar/process/ProcessWrapper.java @@ -60,7 +60,7 @@ public class ProcessWrapper extends Thread { private final List javaOpts = new ArrayList(); private final List classpath = new ArrayList(); private final Map envProperties = new HashMap(); - private final Map arguments = new HashMap(); + private final Map properties = new HashMap(); private File workDir; private File propertiesFile; private java.lang.Process process; @@ -82,14 +82,14 @@ public class ProcessWrapper extends Thread { return this; } - public ProcessWrapper setArgument(String key, String value) { - arguments.put(key, value); + public ProcessWrapper setProperty(String key, String value) { + properties.put(key, value); return this; } - public ProcessWrapper setArguments(Map args) { - arguments.clear(); - arguments.putAll(args); + public ProcessWrapper setProperties(Map args) { + properties.clear(); + properties.putAll(args); return this; } @@ -125,7 +125,7 @@ public class ProcessWrapper extends Thread { return this; } - public void execute() { + public ProcessWrapper execute() { List command = new ArrayList(); command.add(buildJavaCommand()); command.addAll(javaOpts); @@ -137,6 +137,7 @@ public class ProcessWrapper extends Thread { ProcessBuilder processBuilder = new ProcessBuilder(); processBuilder.command(command); processBuilder.directory(workDir); + processBuilder.environment().putAll(envProperties); try { LOGGER.debug("ProcessWrapper::executeProcess() -- Starting process with command '{}'", StringUtils.join(command, " ")); @@ -147,6 +148,7 @@ public class ProcessWrapper extends Thread { outputGobbler.start(); errorGobbler.start(); processMXBean = waitForJMX(); + return this; } catch (IOException e) { throw new IllegalStateException("Fail to start process: " + StringUtils.join(command, " "), e); @@ -214,14 +216,14 @@ public class ProcessWrapper extends Thread { } private List buildClasspath() { - return Arrays.asList("-cp", StringUtils.join(classpath, ";")); + return Arrays.asList("-cp", StringUtils.join(classpath, System.getProperty("path.separator"))); } private File buildPropertiesFile() { try { propertiesFile = File.createTempFile("sq-conf", "properties"); Properties props = new Properties(); - props.putAll(arguments); + props.putAll(properties); props.put(Process.NAME_PROPERTY, processName); props.put(Process.PORT_PROPERTY, String.valueOf(jmxPort)); OutputStream out = new FileOutputStream(propertiesFile); diff --git a/server/sonar-search/src/main/java/org/sonar/search/ElasticSearch.java b/server/sonar-search/src/main/java/org/sonar/search/ElasticSearch.java index c2c1b2bac96..ea1b4f95b15 100644 --- a/server/sonar-search/src/main/java/org/sonar/search/ElasticSearch.java +++ b/server/sonar-search/src/main/java/org/sonar/search/ElasticSearch.java @@ -34,11 +34,9 @@ import java.io.File; public class ElasticSearch extends Process { public static final String ES_DEBUG_PROPERTY = "esDebug"; - public static final String ES_PORT_PROPERTY = "sonar.es.node.port"; + public static final String ES_PORT_PROPERTY = "sonar.es.port"; public static final String ES_CLUSTER_PROPERTY = "sonar.es.cluster.name"; - public static final String DEFAULT_CLUSTER_NAME = "sonarqube"; - private Node node; public ElasticSearch(String... args) { @@ -121,7 +119,7 @@ public class ElasticSearch extends Process { public void onStart() { String dataDir = props.of("sonar.path.data"); Integer port = props.intOf(ES_PORT_PROPERTY); - String clusterName = props.of(ES_CLUSTER_PROPERTY, DEFAULT_CLUSTER_NAME); + String clusterName = props.of(ES_CLUSTER_PROPERTY); LoggerFactory.getLogger(ElasticSearch.class).info("Starting ES[{}] on port: {}", clusterName, port); diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java b/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java index cceb7c4cb43..41035bacce9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java @@ -24,7 +24,6 @@ import org.apache.commons.io.filefilter.FileFilterUtils; import org.picocontainer.Startable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.platform.Server; import org.sonar.api.platform.ServerFileSystem; @@ -32,7 +31,6 @@ import org.sonar.core.persistence.Database; import org.sonar.core.persistence.dialect.H2; import javax.annotation.CheckForNull; - import java.io.File; import java.io.FileFilter; import java.io.IOException; @@ -71,16 +69,10 @@ public class DefaultServerFileSystem implements ServerFileSystem, Startable { @Override public void start() { LOGGER.info("SonarQube home: " + homeDir.getAbsolutePath()); - if (!homeDir.isDirectory() || !homeDir.exists()) { - throw new IllegalStateException("SonarQube home directory does not exist"); - } - try { if (getDeployDir() == null) { throw new IllegalArgumentException("Web app directory does not exist: " + getDeployDir()); } - - LOGGER.info("Deploy dir: " + getDeployDir().getAbsolutePath()); FileUtils.forceMkdir(getDeployDir()); for (File subDirectory : getDeployDir().listFiles((FileFilter) FileFilterUtils.directoryFileFilter())) { FileUtils.cleanDirectory(subDirectory); diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/PlatformServletContextListener.java b/server/sonar-server/src/main/java/org/sonar/server/platform/PlatformServletContextListener.java index ab87e7db4b8..250832144d1 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/PlatformServletContextListener.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/PlatformServletContextListener.java @@ -100,7 +100,6 @@ public final class PlatformServletContextListener implements ServletContextListe // Line below used in last resort "false"); Map variables = ImmutableMap.of( - "RAILS_LOGGER_LEVEL", profilingLevel == Profiling.Level.FULL ? "DEBUG" : "WARN", "LOGFILE_LOGGING_FORMAT", profilingLevel == Profiling.Level.FULL ? LOGFILE_FULL_LOGGING_FORMAT : LOGFILE_STANDARD_LOGGING_FORMAT, "CONSOLE_LOGGING_FORMAT", profilingLevel == Profiling.Level.FULL ? CONSOLE_FULL_LOGGING_FORMAT : CONSOLE_STANDARD_LOGGING_FORMAT, "CONSOLE_ENABLED", consoleEnabled); diff --git a/server/sonar-server/src/main/java/org/sonar/server/search/IndexProperties.java b/server/sonar-server/src/main/java/org/sonar/server/search/IndexProperties.java index 007b5689883..996c8ec477c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/search/IndexProperties.java +++ b/server/sonar-server/src/main/java/org/sonar/server/search/IndexProperties.java @@ -31,7 +31,7 @@ public final class IndexProperties { public static final String TYPE = "sonar.es.type"; public static final String HTTP_PORT = "sonar.es.http.port"; - public static final String NODE_PORT = "sonar.es.node.port"; + public static final String NODE_PORT = "sonar.es.port"; public static final String CLUSTER_NAME = "sonar.es.cluster.name"; } diff --git a/sonar-application/pom.xml b/sonar-application/pom.xml index 2ac77222a32..14d129a9dfc 100644 --- a/sonar-application/pom.xml +++ b/sonar-application/pom.xml @@ -237,8 +237,8 @@ - 85000000 - 95000000 + 100000000 + 105000000 ${project.build.directory}/sonarqube-${project.version}.zip diff --git a/sonar-application/src/main/assembly/conf/sonar.properties b/sonar-application/src/main/assembly/conf/sonar.properties index e2ab2aad13a..bc2243f37da 100644 --- a/sonar-application/src/main/assembly/conf/sonar.properties +++ b/sonar-application/src/main/assembly/conf/sonar.properties @@ -4,9 +4,7 @@ # To use an environment variable, use the following syntax : ${env:NAME_OF_ENV_VARIABLE} # For example: # sonar.jdbc.url= ${env:SONAR_JDBC_URL} -# -# -# See also the file conf/wrapper.conf for JVM advanced settings + #-------------------------------------------------------------------------------------------------- # TO BE DOCUMENTED - WORK IN PROGRESS @@ -17,7 +15,7 @@ # For debug only #sonar.es.httpPort= -#sonar.web.javaOpts=-server -Xmx768m -Djava.awt.headless=true -XX:MaxPermSize=160m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Djruby.management.enabled=false +#sonar.web.javaOpts=-server -Xmx768m -XX:MaxPermSize=160m -XX:+HeapDumpOnOutOfMemoryError #sonar.web.jmxPort=0 # Paths are absolute or relative to installation root directory diff --git a/sonar-application/src/main/assembly/conf/wrapper.conf b/sonar-application/src/main/assembly/conf/wrapper.conf index 74f08ffddf1..21fd822b0f8 100644 --- a/sonar-application/src/main/assembly/conf/wrapper.conf +++ b/sonar-application/src/main/assembly/conf/wrapper.conf @@ -4,7 +4,7 @@ wrapper.disable_restarts=TRUE # Java Additional Parameters -wrapper.java.additional.1=-Xmx32M +wrapper.java.additional.1=-Xmx16m # Initial JVM heap size (in MB) wrapper.java.initmemory=16 @@ -28,7 +28,6 @@ wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp wrapper.java.classpath.1=../../lib/common/*.jar wrapper.java.classpath.2=../../lib/*.jar - # Java Library Path (location of Wrapper.DLL or libwrapper.so) wrapper.java.library.path.1=./lib @@ -106,5 +105,4 @@ wrapper.ntservice.starttype=AUTO_START wrapper.ntservice.interactive=false #******************************************************************** -# restart the process if CPU is heavily loaded during 240 seconds. wrapper.ping.timeout=0 diff --git a/sonar-application/src/main/java/org/sonar/application/Installation.java b/sonar-application/src/main/java/org/sonar/application/Installation.java index 41b87b60b15..924c4f4eb38 100644 --- a/sonar-application/src/main/java/org/sonar/application/Installation.java +++ b/sonar-application/src/main/java/org/sonar/application/Installation.java @@ -22,6 +22,9 @@ package org.sonar.application; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.process.NetworkUtils; import javax.annotation.CheckForNull; import javax.annotation.Nullable; @@ -34,18 +37,34 @@ import java.util.Map; import java.util.Properties; public class Installation { + private static final Logger LOG = LoggerFactory.getLogger(Installation.class); // guessed from location of sonar-application.jar private final File homeDir; private final File tempDir, dataDir, logsDir, webDir; - private final Map props = new HashMap(); + private final Map props; Installation() throws URISyntaxException, IOException { - // TODO make it configurable with sonar.path.home ? // lib/sonar-application.jar File appJar = new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()); homeDir = appJar.getParentFile().getParentFile(); + props = initProps(homeDir); + + // init file system + props.put("sonar.path.home", homeDir.getAbsolutePath()); + this.dataDir = existingDir("sonar.path.data", "data"); + this.tempDir = freshDir("sonar.path.temp", "temp"); + this.logsDir = existingDir("sonar.path.logs", "logs"); + this.webDir = existingDir("sonar.path.web", "web"); + + initElasticsearch(); + } + + /** + * Load conf/sonar.properties + */ + private static Map initProps(File homeDir) throws IOException { Properties p = new Properties(); File propsFile = new File(homeDir, "conf/sonar.properties"); if (propsFile.exists()) { @@ -55,22 +74,31 @@ public class Installation { } finally { IOUtils.closeQuietly(reader); } + } else { + LOG.info("Configuration file not found: " + propsFile.getAbsolutePath()); } p.putAll(System.getenv()); p.putAll(System.getProperties()); p = ConfigurationUtils.interpolateEnvVariables(p); + Map result = new HashMap(); for (Map.Entry entry : p.entrySet()) { Object val = entry.getValue(); if (val != null) { - this.props.put(entry.getKey().toString(), val.toString()); + result.put(entry.getKey().toString(), val.toString()); } } + return result; + } - props.put("sonar.path.home", homeDir.getAbsolutePath()); - this.dataDir = existingDir("sonar.path.data", "data"); - this.tempDir = freshDir("sonar.path.temp", "temp"); - this.logsDir = existingDir("sonar.path.logs", "logs"); - this.webDir = existingDir("sonar.path.web", "web"); + private void initElasticsearch() { + // init Elasticsearch + if (props.get("sonar.es.port") == null) { + props.put("sonar.es.port", String.valueOf(NetworkUtils.freePort())); + } + if (props.get("sonar.es.cluster.name") == null) { + props.put("sonar.es.cluster.name", "sonarqube"); + } + props.put("sonar.es.type", "TRANSPORT"); } File homeDir() { @@ -128,6 +156,10 @@ public class Installation { return props; } + String prop(String key) { + return props.get(key); + } + @CheckForNull String prop(String key, @Nullable String defaultValue) { String s = props.get(key); diff --git a/sonar-application/src/main/java/org/sonar/application/StartServer.java b/sonar-application/src/main/java/org/sonar/application/StartServer.java index c485c489efe..bb856695260 100644 --- a/sonar-application/src/main/java/org/sonar/application/StartServer.java +++ b/sonar-application/src/main/java/org/sonar/application/StartServer.java @@ -34,15 +34,6 @@ public class StartServer { public StartServer() throws Exception { Installation installation = new Installation(); - String esPort = installation.prop("sonar.es.node.port", null); - if (esPort == null) { - esPort = String.valueOf(NetworkUtils.freePort()); - } - String esCluster = installation.prop("sonar.es.cluster.name", null); - if (esCluster == null) { - installation.setProp("sonar.es.cluster.name", "sonarqube"); - } - shutdownHook = new Thread(new Runnable() { @Override public void run() { @@ -57,29 +48,35 @@ public class StartServer { String opts = installation.prop("sonar.es.javaOpts", "-server -Xmx256m -Xms128m -Xss256k -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly"); elasticsearch = new ProcessWrapper("ES") .setWorkDir(installation.homeDir()) + .setJmxPort(NetworkUtils.freePort()) .addJavaOpts(opts) + .addJavaOpts("-Djava.io.tmpdir=" + installation.tempDir().getAbsolutePath()) + .setEnvProperty("SONAR_HOME", installation.homeDir().getAbsolutePath()) .setClassName("org.sonar.search.ElasticSearch") - .setArguments(installation.props()) - .setArgument("sonar.es.node.port", esPort) + .setProperties(installation.props()) .addClasspath(installation.starPath("lib/common")) - .addClasspath(installation.starPath("lib/search")); + .addClasspath(installation.starPath("lib/search")) + .execute(); monitor.registerProcess(elasticsearch); - opts = installation.prop("sonar.web.javaOpts", "-Xmx768m -server -XX:MaxPermSize=160m -Djava.awt.headless=true -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Djruby.management.enabled=false"); + opts = installation.prop("sonar.web.javaOpts", "-Xmx768m -server -XX:MaxPermSize=160m -XX:+HeapDumpOnOutOfMemoryError"); server = new ProcessWrapper("SQ") .setWorkDir(installation.homeDir()) + .setJmxPort(NetworkUtils.freePort()) .addJavaOpts(opts) + .addJavaOpts("-Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djruby.management.enabled=false") + .addJavaOpts("-Djava.io.tmpdir=" + installation.tempDir().getAbsolutePath()) .setClassName("org.sonar.server.app.ServerProcess") .setEnvProperty("SONAR_HOME", installation.homeDir().getAbsolutePath()) - .setArguments(installation.props()) - .setArgument("sonar.es.type", "TRANSPORT") + .setProperties(installation.props()) .addClasspath(installation.starPath("extensions/jdbc-driver/mysql")) .addClasspath(installation.starPath("extensions/jdbc-driver/mssql")) .addClasspath(installation.starPath("extensions/jdbc-driver/oracle")) .addClasspath(installation.starPath("extensions/jdbc-driver/postgresql")) .addClasspath(installation.starPath("lib/common")) - .addClasspath(installation.starPath("lib/server")); + .addClasspath(installation.starPath("lib/server")) + .execute(); monitor.registerProcess(server); monitor.start(); -- 2.39.5