You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CommandFactoryImpl.java 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2018 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.application.command;
  21. import java.io.File;
  22. import java.util.Map;
  23. import java.util.Optional;
  24. import org.slf4j.LoggerFactory;
  25. import org.sonar.application.es.EsInstallation;
  26. import org.sonar.application.es.EsLogging;
  27. import org.sonar.application.es.EsSettings;
  28. import org.sonar.application.es.EsYmlSettings;
  29. import org.sonar.process.ProcessId;
  30. import org.sonar.process.Props;
  31. import org.sonar.process.System2;
  32. import static org.sonar.process.ProcessProperties.Property.CE_JAVA_ADDITIONAL_OPTS;
  33. import static org.sonar.process.ProcessProperties.Property.CE_JAVA_OPTS;
  34. import static org.sonar.process.ProcessProperties.Property.HTTPS_PROXY_HOST;
  35. import static org.sonar.process.ProcessProperties.Property.HTTPS_PROXY_PORT;
  36. import static org.sonar.process.ProcessProperties.Property.HTTP_AUTH_NLM_DOMAN;
  37. import static org.sonar.process.ProcessProperties.Property.HTTP_NON_PROXY_HOSTS;
  38. import static org.sonar.process.ProcessProperties.Property.HTTP_PROXY_HOST;
  39. import static org.sonar.process.ProcessProperties.Property.HTTP_PROXY_PORT;
  40. import static org.sonar.process.ProcessProperties.Property.JDBC_DRIVER_PATH;
  41. import static org.sonar.process.ProcessProperties.Property.PATH_HOME;
  42. import static org.sonar.process.ProcessProperties.Property.PATH_LOGS;
  43. import static org.sonar.process.ProcessProperties.Property.SEARCH_JAVA_ADDITIONAL_OPTS;
  44. import static org.sonar.process.ProcessProperties.Property.SEARCH_JAVA_OPTS;
  45. import static org.sonar.process.ProcessProperties.Property.SOCKS_PROXY_HOST;
  46. import static org.sonar.process.ProcessProperties.Property.SOCKS_PROXY_PORT;
  47. import static org.sonar.process.ProcessProperties.Property.WEB_JAVA_ADDITIONAL_OPTS;
  48. import static org.sonar.process.ProcessProperties.Property.WEB_JAVA_OPTS;
  49. public class CommandFactoryImpl implements CommandFactory {
  50. private static final String ENV_VAR_JAVA_TOOL_OPTIONS = "JAVA_TOOL_OPTIONS";
  51. /**
  52. * Properties about proxy that must be set as system properties
  53. */
  54. private static final String[] PROXY_PROPERTY_KEYS = new String[] {
  55. HTTP_PROXY_HOST.getKey(),
  56. HTTP_PROXY_PORT.getKey(),
  57. HTTP_NON_PROXY_HOSTS.getKey(),
  58. HTTPS_PROXY_HOST.getKey(),
  59. HTTPS_PROXY_PORT.getKey(),
  60. HTTP_AUTH_NLM_DOMAN.getKey(),
  61. SOCKS_PROXY_HOST.getKey(),
  62. SOCKS_PROXY_PORT.getKey()};
  63. private final Props props;
  64. private final File tempDir;
  65. private final System2 system2;
  66. public CommandFactoryImpl(Props props, File tempDir, System2 system2) {
  67. this.props = props;
  68. this.tempDir = tempDir;
  69. this.system2 = system2;
  70. String javaToolOptions = system2.getenv(ENV_VAR_JAVA_TOOL_OPTIONS);
  71. if (javaToolOptions != null && !javaToolOptions.trim().isEmpty()) {
  72. LoggerFactory.getLogger(CommandFactoryImpl.class)
  73. .warn("JAVA_TOOL_OPTIONS is defined but will be ignored. " +
  74. "Use properties sonar.*.javaOpts and/or sonar.*.javaAdditionalOpts in sonar.properties to change SQ JVM processes options");
  75. }
  76. }
  77. @Override
  78. public AbstractCommand<?> createEsCommand() {
  79. if (system2.isOsWindows()) {
  80. return createEsCommandForWindows();
  81. }
  82. return createEsCommandForUnix();
  83. }
  84. private EsScriptCommand createEsCommandForUnix() {
  85. EsInstallation esInstallation = createEsInstallation();
  86. return new EsScriptCommand(ProcessId.ELASTICSEARCH, esInstallation.getHomeDirectory())
  87. .setEsInstallation(esInstallation)
  88. .addOption("-Epath.conf=" + esInstallation.getConfDirectory().getAbsolutePath())
  89. .setEnvVariable("ES_JVM_OPTIONS", esInstallation.getJvmOptions().getAbsolutePath())
  90. .setEnvVariable("JAVA_HOME", System.getProperties().getProperty("java.home"))
  91. .suppressEnvVariable(ENV_VAR_JAVA_TOOL_OPTIONS);
  92. }
  93. private JavaCommand createEsCommandForWindows() {
  94. EsInstallation esInstallation = createEsInstallation();
  95. return new JavaCommand<EsJvmOptions>(ProcessId.ELASTICSEARCH, esInstallation.getHomeDirectory())
  96. .setEsInstallation(esInstallation)
  97. .setReadsArgumentsFromFile(false)
  98. .setArgument("path.conf", esInstallation.getConfDirectory().getAbsolutePath())
  99. .setJvmOptions(new EsJvmOptions()
  100. .addFromMandatoryProperty(props, SEARCH_JAVA_OPTS.getKey())
  101. .addFromMandatoryProperty(props, SEARCH_JAVA_ADDITIONAL_OPTS.getKey())
  102. .add("-Delasticsearch")
  103. .add("-Des.path.home=" + esInstallation.getHomeDirectory()))
  104. .setEnvVariable("ES_JVM_OPTIONS", esInstallation.getJvmOptions().getAbsolutePath())
  105. .setEnvVariable("JAVA_HOME", System.getProperties().getProperty("java.home"))
  106. .setClassName("org.elasticsearch.bootstrap.Elasticsearch")
  107. .addClasspath("lib/*")
  108. .suppressEnvVariable(ENV_VAR_JAVA_TOOL_OPTIONS);
  109. }
  110. private EsInstallation createEsInstallation() {
  111. EsInstallation esInstallation = new EsInstallation(props);
  112. if (!esInstallation.getExecutable().exists()) {
  113. throw new IllegalStateException("Cannot find elasticsearch binary");
  114. }
  115. Map<String, String> settingsMap = new EsSettings(props, esInstallation, System2.INSTANCE).build();
  116. esInstallation
  117. .setLog4j2Properties(new EsLogging().createProperties(props, esInstallation.getLogDirectory()))
  118. .setEsJvmOptions(new EsJvmOptions()
  119. .addFromMandatoryProperty(props, SEARCH_JAVA_OPTS.getKey())
  120. .addFromMandatoryProperty(props, SEARCH_JAVA_ADDITIONAL_OPTS.getKey()))
  121. .setEsYmlSettings(new EsYmlSettings(settingsMap))
  122. .setClusterName(settingsMap.get("cluster.name"))
  123. .setHost(settingsMap.get("network.host"))
  124. .setPort(Integer.valueOf(settingsMap.get("transport.tcp.port")));
  125. return esInstallation;
  126. }
  127. @Override
  128. public JavaCommand createWebCommand(boolean leader) {
  129. File homeDir = props.nonNullValueAsFile(PATH_HOME.getKey());
  130. WebJvmOptions jvmOptions = new WebJvmOptions(tempDir)
  131. .addFromMandatoryProperty(props, WEB_JAVA_OPTS.getKey())
  132. .addFromMandatoryProperty(props, WEB_JAVA_ADDITIONAL_OPTS.getKey());
  133. addProxyJvmOptions(jvmOptions);
  134. JavaCommand<WebJvmOptions> command = new JavaCommand<WebJvmOptions>(ProcessId.WEB_SERVER, homeDir)
  135. .setReadsArgumentsFromFile(true)
  136. .setArguments(props.rawProperties())
  137. .setJvmOptions(jvmOptions)
  138. // required for logback tomcat valve
  139. .setEnvVariable(PATH_LOGS.getKey(), props.nonNullValue(PATH_LOGS.getKey()))
  140. .setArgument("sonar.cluster.web.startupLeader", Boolean.toString(leader))
  141. .setClassName("org.sonar.server.app.WebServer")
  142. .addClasspath("./lib/common/*");
  143. String driverPath = props.value(JDBC_DRIVER_PATH.getKey());
  144. if (driverPath != null) {
  145. command.addClasspath(driverPath);
  146. }
  147. command.suppressEnvVariable(ENV_VAR_JAVA_TOOL_OPTIONS);
  148. return command;
  149. }
  150. @Override
  151. public JavaCommand createCeCommand() {
  152. File homeDir = props.nonNullValueAsFile(PATH_HOME.getKey());
  153. CeJvmOptions jvmOptions = new CeJvmOptions(tempDir)
  154. .addFromMandatoryProperty(props, CE_JAVA_OPTS.getKey())
  155. .addFromMandatoryProperty(props, CE_JAVA_ADDITIONAL_OPTS.getKey());
  156. addProxyJvmOptions(jvmOptions);
  157. JavaCommand<CeJvmOptions> command = new JavaCommand<CeJvmOptions>(ProcessId.COMPUTE_ENGINE, homeDir)
  158. .setReadsArgumentsFromFile(true)
  159. .setArguments(props.rawProperties())
  160. .setJvmOptions(jvmOptions)
  161. .setClassName("org.sonar.ce.app.CeServer")
  162. .addClasspath("./lib/common/*");
  163. String driverPath = props.value(JDBC_DRIVER_PATH.getKey());
  164. if (driverPath != null) {
  165. command.addClasspath(driverPath);
  166. }
  167. command.suppressEnvVariable(ENV_VAR_JAVA_TOOL_OPTIONS);
  168. return command;
  169. }
  170. private <T extends JvmOptions> void addProxyJvmOptions(JvmOptions<T> jvmOptions) {
  171. for (String key : PROXY_PROPERTY_KEYS) {
  172. getPropsValue(key).ifPresent(val -> jvmOptions.add("-D" + key + "=" + val));
  173. }
  174. // defaults of HTTPS are the same than HTTP defaults
  175. setSystemPropertyToDefaultIfNotSet(jvmOptions, HTTPS_PROXY_HOST.getKey(), HTTP_PROXY_HOST.getKey());
  176. setSystemPropertyToDefaultIfNotSet(jvmOptions, HTTPS_PROXY_PORT.getKey(), HTTP_PROXY_PORT.getKey());
  177. }
  178. private void setSystemPropertyToDefaultIfNotSet(JvmOptions jvmOptions,
  179. String httpsProperty, String httpProperty) {
  180. Optional<String> httpValue = getPropsValue(httpProperty);
  181. Optional<String> httpsValue = getPropsValue(httpsProperty);
  182. if (!httpsValue.isPresent() && httpValue.isPresent()) {
  183. jvmOptions.add("-D" + httpsProperty + "=" + httpValue.get());
  184. }
  185. }
  186. private Optional<String> getPropsValue(String key) {
  187. return Optional.ofNullable(props.value(key));
  188. }
  189. }