aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2016-02-04 22:42:10 +0100
committerSimon Brandhof <simon.brandhof@sonarsource.com>2016-02-05 14:24:25 +0100
commit39cc96f13fff24c17bb9b1a37311cd37281f6e03 (patch)
tree835c9e3cb10f704a9e1551b12fe91d393f086570
parent8115b23fa61b022377a5fc150ac2b3ec2ca11d97 (diff)
downloadsonarqube-39cc96f13fff24c17bb9b1a37311cd37281f6e03.tar.gz
sonarqube-39cc96f13fff24c17bb9b1a37311cd37281f6e03.zip
SONAR-6740 refactor configuration of Tomcat contexts
It allows to remove some warnings on static context when server fails to start.
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/app/EmbeddedTomcat.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/app/TomcatContexts.java (renamed from server/sonar-server/src/main/java/org/sonar/server/app/Webapp.java)90
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/app/WebDeployContext.java63
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerImpl.java4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/app/TomcatContextsTest.java (renamed from server/sonar-server/src/test/java/org/sonar/server/app/WebappTest.java)86
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/app/WebDeployContextTest.java87
6 files changed, 125 insertions, 207 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/app/EmbeddedTomcat.java b/server/sonar-server/src/main/java/org/sonar/server/app/EmbeddedTomcat.java
index 5f3bad375c3..39b5d5c1e0a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/app/EmbeddedTomcat.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/app/EmbeddedTomcat.java
@@ -56,7 +56,7 @@ class EmbeddedTomcat {
tomcat.getHost().setDeployOnStartup(true);
new TomcatAccessLog().configure(tomcat, props);
TomcatConnectors.configure(tomcat, props);
- webappContext = Webapp.configure(tomcat, props);
+ webappContext = new TomcatContexts().configure(tomcat, props);
try {
tomcat.start();
new TomcatStartupLogs(props, Loggers.get(getClass())).log(tomcat);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/app/Webapp.java b/server/sonar-server/src/main/java/org/sonar/server/app/TomcatContexts.java
index bee8e2063dc..1d25678edef 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/app/Webapp.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/app/TomcatContexts.java
@@ -19,34 +19,73 @@
*/
package org.sonar.server.app;
+import com.google.common.annotations.VisibleForTesting;
import java.io.File;
+import java.io.IOException;
import java.util.Map;
+import javax.servlet.ServletException;
import org.apache.catalina.Context;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.io.FileUtils;
import org.sonar.api.utils.log.Loggers;
import org.sonar.process.ProcessProperties;
import org.sonar.process.Props;
+import static java.lang.String.format;
+import static org.apache.commons.lang.StringUtils.isEmpty;
+
/**
- * Configures webapp into Tomcat
+ * Configures Tomcat contexts:
+ * <ul>
+ * <li>/deploy delivers the plugins required by analyzers. It maps directory ${sonar.path.data}/web/deploy.</li>
+ * <li>/ is the regular webapp</li>
+ * </ul>
*/
-class Webapp {
+public class TomcatContexts {
private static final String JRUBY_MAX_RUNTIMES = "jruby.max.runtimes";
private static final String RAILS_ENV = "rails.env";
private static final String ROOT_CONTEXT_PATH = "";
+ public static final String WEB_DEPLOY_PATH_RELATIVE_TO_DATA_DIR = "web/deploy";
+
+ private final Fs fs;
- private Webapp() {
+ public TomcatContexts() {
+ this.fs = new Fs();
}
- static StandardContext configure(Tomcat tomcat, Props props) {
+ @VisibleForTesting
+ TomcatContexts(Fs fs) {
+ this.fs = fs;
+ }
+
+ public StandardContext configure(Tomcat tomcat, Props props) {
+ addStaticDir(tomcat, "/deploy", new File(props.nonNullValueAsFile(ProcessProperties.PATH_DATA), WEB_DEPLOY_PATH_RELATIVE_TO_DATA_DIR));
+
+ StandardContext webapp = addContext(tomcat, ROOT_CONTEXT_PATH, webappDir(props));
+ configureRails(props, webapp);
+ for (Map.Entry<Object, Object> entry : props.rawProperties().entrySet()) {
+ String key = entry.getKey().toString();
+ webapp.addParameter(key, entry.getValue().toString());
+ }
+ return webapp;
+ }
+
+ @VisibleForTesting
+ StandardContext addStaticDir(Tomcat tomcat, String contextPath, File dir) {
try {
- // URL /deploy must serve files deployed during startup into DATA_DIR/web/deploy
- new WebDeployContext().configureTomcat(tomcat, props);
+ fs.createOrCleanupDir(dir);
+ } catch (IOException e) {
+ throw new IllegalStateException(format("Fail to create or clean-up directory %s", dir.getAbsolutePath()), e);
+ }
- StandardContext context = (StandardContext) tomcat.addWebapp(ROOT_CONTEXT_PATH, webappPath(props));
+ return addContext(tomcat, contextPath, dir);
+ }
+
+ private StandardContext addContext(Tomcat tomcat, String contextPath, File dir) {
+ try {
+ StandardContext context = (StandardContext) tomcat.addWebapp(contextPath, dir.getAbsolutePath());
context.setClearReferencesHttpClientKeepAliveThread(false);
context.setClearReferencesStatic(false);
context.setClearReferencesStopThreads(false);
@@ -61,16 +100,9 @@ class Webapp {
context.setUseNaming(false);
context.setDelegate(true);
context.setJarScanner(new NullJarScanner());
- configureRails(props, context);
-
- for (Map.Entry<Object, Object> entry : props.rawProperties().entrySet()) {
- String key = entry.getKey().toString();
- context.addParameter(key, entry.getValue().toString());
- }
return context;
-
- } catch (Exception e) {
- throw new IllegalStateException("Fail to configure webapp", e);
+ } catch (ServletException e) {
+ throw new IllegalStateException("Fail to configure webapp from " + dir, e);
}
}
@@ -82,19 +114,29 @@ class Webapp {
if (props.valueAsBoolean("sonar.web.dev", false)) {
context.addParameter(RAILS_ENV, "development");
context.addParameter(JRUBY_MAX_RUNTIMES, "3");
- Loggers.get(Webapp.class).warn("WEB DEVELOPMENT MODE IS ENABLED - DO NOT USE FOR PRODUCTION USAGE");
+ Loggers.get(TomcatContexts.class).warn("WEB DEVELOPMENT MODE IS ENABLED - DO NOT USE FOR PRODUCTION USAGE");
} else {
context.addParameter(RAILS_ENV, "production");
context.addParameter(JRUBY_MAX_RUNTIMES, "1");
}
}
- static String webappPath(Props props) {
- String webDir = props.value("sonar.web.dev.sources");
- if (StringUtils.isEmpty(webDir)) {
- webDir = new File(props.value(ProcessProperties.PATH_HOME), "web").getAbsolutePath();
+ static File webappDir(Props props) {
+ String devDir = props.value("sonar.web.dev.sources");
+ File dir;
+ if (isEmpty(devDir)) {
+ dir = new File(props.value(ProcessProperties.PATH_HOME), "web");
+ } else {
+ dir = new File(devDir);
+ }
+ Loggers.get(TomcatContexts.class).info("Webapp directory: {}", dir);
+ return dir;
+ }
+
+ static class Fs {
+ void createOrCleanupDir(File dir) throws IOException {
+ FileUtils.forceMkdir(dir);
+ FileUtils.cleanDirectory(dir);
}
- Loggers.get(Webapp.class).info(String.format("Webapp directory: %s", webDir));
- return webDir;
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/app/WebDeployContext.java b/server/sonar-server/src/main/java/org/sonar/server/app/WebDeployContext.java
deleted file mode 100644
index 688271a79ac..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/app/WebDeployContext.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * 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 02110-1301, USA.
- */
-package org.sonar.server.app;
-
-import com.google.common.annotations.VisibleForTesting;
-import java.io.File;
-import java.io.IOException;
-import javax.servlet.ServletException;
-import org.apache.catalina.startup.Tomcat;
-import org.apache.commons.io.FileUtils;
-import org.sonar.process.ProcessProperties;
-import org.sonar.process.Props;
-
-import static java.lang.String.format;
-
-public class WebDeployContext {
-
- public static final String RELATIVE_DIR_IN_DATA = "web/deploy";
- private final Fs fs;
-
- public WebDeployContext() {
- this(new Fs());
- }
-
- @VisibleForTesting
- public WebDeployContext(Fs fs) {
- this.fs = fs;
- }
-
- public void configureTomcat(Tomcat tomcat, Props props) throws ServletException {
- File deployDir = new File(props.nonNullValueAsFile(ProcessProperties.PATH_DATA), RELATIVE_DIR_IN_DATA);
- try {
- fs.createOrCleanupDir(deployDir);
- } catch (IOException e) {
- throw new IllegalStateException(format("Fail to create or clean-up directory %s", deployDir.getAbsolutePath()), e);
- }
- tomcat.addWebapp("/deploy", deployDir.getAbsolutePath());
- }
-
- static class Fs {
- void createOrCleanupDir(File dir) throws IOException {
- FileUtils.forceMkdir(dir);
- FileUtils.cleanDirectory(dir);
- }
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerImpl.java
index cf6bd157eba..3ec74f8c306 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerImpl.java
@@ -41,7 +41,7 @@ import org.sonar.api.platform.Server;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.process.ProcessProperties;
-import org.sonar.server.app.WebDeployContext;
+import org.sonar.server.app.TomcatContexts;
import static org.sonar.api.CoreProperties.SERVER_BASE_URL;
import static org.sonar.api.CoreProperties.SERVER_BASE_URL_DEFAULT_VALUE;
@@ -84,7 +84,7 @@ public final class ServerImpl extends Server implements Startable {
throw new IllegalStateException("SonarQube home directory is not valid");
}
- deployDir = new File(settings.getString(ProcessProperties.PATH_DATA), WebDeployContext.RELATIVE_DIR_IN_DATA);
+ deployDir = new File(settings.getString(ProcessProperties.PATH_DATA), TomcatContexts.WEB_DEPLOY_PATH_RELATIVE_TO_DATA_DIR);
LOG.info("SonarQube {}", Joiner.on(" / ").skipNulls().join("Server", version, implementationBuild));
diff --git a/server/sonar-server/src/test/java/org/sonar/server/app/WebappTest.java b/server/sonar-server/src/test/java/org/sonar/server/app/TomcatContextsTest.java
index 8b8a2f2a935..e54244c4304 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/app/WebappTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/app/TomcatContextsTest.java
@@ -25,56 +25,47 @@ import java.util.Properties;
import org.apache.catalina.Context;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
+import org.apache.commons.io.FileUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.sonar.process.ProcessProperties;
import org.sonar.process.Props;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-public class WebappTest {
+public class TomcatContextsTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- Props props = new Props(new Properties());
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
- @Before
- public void initDataDir() throws Exception {
- props.set(ProcessProperties.PATH_DATA, temp.newFolder("data").getAbsolutePath());
- }
+ Tomcat tomcat = mock(Tomcat.class);
+ Properties props = new Properties();
- @Test
- public void fail_on_error() throws Exception {
- File webDir = temp.newFolder("web");
-
- Tomcat tomcat = mock(Tomcat.class, RETURNS_DEEP_STUBS);
- when(tomcat.addContext("", webDir.getAbsolutePath())).thenThrow(new NullPointerException());
-
- try {
- Webapp.configure(tomcat, props);
- fail();
- } catch (IllegalStateException e) {
- assertThat(e).hasMessage("Fail to configure webapp");
- }
+ @Before
+ public void setUp() throws Exception {
+ props.setProperty(ProcessProperties.PATH_DATA, temp.newFolder("data").getAbsolutePath());
+ when(tomcat.addWebapp(anyString(), anyString())).thenReturn(mock(StandardContext.class));
}
@Test
- public void configure_context() throws Exception {
- props.set("foo", "bar");
+ public void configure_root_webapp() throws Exception {
+ props.setProperty("foo", "bar");
StandardContext context = mock(StandardContext.class);
- Tomcat tomcat = mock(Tomcat.class);
when(tomcat.addWebapp(anyString(), anyString())).thenReturn(context);
- Webapp.configure(tomcat, props);
+ new TomcatContexts().configure(tomcat, new Props(props));
// configure webapp with properties
verify(context).addParameter("foo", "bar");
@@ -82,23 +73,58 @@ public class WebappTest {
@Test
public void configure_rails_dev_mode() {
- props.set("sonar.web.dev", "true");
+ props.setProperty("sonar.web.dev", "true");
Context context = mock(Context.class);
- Webapp.configureRails(props, context);
+ new TomcatContexts().configureRails(new Props(props), context);
verify(context).addParameter("jruby.max.runtimes", "3");
verify(context).addParameter("rails.env", "development");
}
@Test
- public void configure_production_mode() {
- props.set("sonar.web.dev", "false");
+ public void configure_rails_production_mode() {
+ props.setProperty("sonar.web.dev", "false");
Context context = mock(Context.class);
- Webapp.configureRails(props, context);
+ new TomcatContexts().configureRails(new Props(props), context);
verify(context).addParameter("jruby.max.runtimes", "1");
verify(context).addParameter("rails.env", "production");
}
+
+ @Test
+ public void create_dir_and_configure_static_directory() throws Exception {
+ File dir = temp.newFolder();
+ dir.delete();
+
+ new TomcatContexts().addStaticDir(tomcat, "/deploy", dir);
+
+ assertThat(dir).isDirectory().exists();
+ verify(tomcat).addWebapp("/deploy", dir.getAbsolutePath());
+ }
+
+ @Test
+ public void cleanup_static_directory_if_already_exists() throws Exception {
+ File dir = temp.newFolder();
+ FileUtils.touch(new File(dir, "foo.txt"));
+
+ new TomcatContexts().addStaticDir(tomcat, "/deploy", dir);
+
+ assertThat(dir).isDirectory().exists();
+ assertThat(dir.listFiles()).isEmpty();
+ }
+
+ @Test
+ public void fail_if_static_directory_can_not_be_initialized() throws Exception {
+ File dir = temp.newFolder();
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Fail to create or clean-up directory " + dir.getAbsolutePath());
+
+ TomcatContexts.Fs fs = mock(TomcatContexts.Fs.class);
+ doThrow(new IOException()).when(fs).createOrCleanupDir(any(File.class));
+
+ new TomcatContexts(fs).addStaticDir(tomcat, "/deploy", dir);
+
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/app/WebDeployContextTest.java b/server/sonar-server/src/test/java/org/sonar/server/app/WebDeployContextTest.java
deleted file mode 100644
index eac45d9d1fe..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/app/WebDeployContextTest.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2016 SonarSource SA
- * mailto:contact AT sonarsource DOT com
- *
- * 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 02110-1301, USA.
- */
-package org.sonar.server.app;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Properties;
-import org.apache.catalina.startup.Tomcat;
-import org.apache.commons.io.FileUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.process.ProcessProperties;
-import org.sonar.process.Props;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-public class WebDeployContextTest {
-
- @Rule
- public TemporaryFolder temp = new TemporaryFolder();
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- Tomcat tomcat = mock(Tomcat.class);
- Properties props = new Properties();
-
- @Test
- public void create_dir_and_configure_tomcat_context() throws Exception {
- File dataDir = temp.newFolder();
- props.setProperty(ProcessProperties.PATH_DATA, dataDir.getAbsolutePath());
- new WebDeployContext().configureTomcat(tomcat, new Props(props));
-
- File deployDir = new File(dataDir, "web/deploy");
- assertThat(deployDir).isDirectory().exists();
- verify(tomcat).addWebapp("/deploy", deployDir.getAbsolutePath());
- }
-
- @Test
- public void cleanup_directory_if_already_exists() throws Exception {
- File dataDir = temp.newFolder();
- File deployDir = new File(dataDir, "web/deploy");
- FileUtils.touch(new File(deployDir, "foo.txt"));
- props.setProperty(ProcessProperties.PATH_DATA, dataDir.getAbsolutePath());
- new WebDeployContext().configureTomcat(tomcat, new Props(props));
-
- assertThat(deployDir).isDirectory().exists();
- assertThat(deployDir.listFiles()).isEmpty();
- }
-
- @Test
- public void fail_if_directory_can_not_be_initialized() throws Exception {
- File dataDir = temp.newFolder();
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Fail to create or clean-up directory " + dataDir.getAbsolutePath());
-
- props.setProperty(ProcessProperties.PATH_DATA, dataDir.getAbsolutePath());
- WebDeployContext.Fs fs = mock(WebDeployContext.Fs.class);
- doThrow(new IOException()).when(fs).createOrCleanupDir(any(File.class));
-
- new WebDeployContext(fs).configureTomcat(tomcat, new Props(props));
-
- }
-}