]> source.dussan.org Git - sonarqube.git/commitdiff
Fix some quality flaws
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 26 Aug 2014 17:14:30 +0000 (19:14 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 26 Aug 2014 17:14:30 +0000 (19:14 +0200)
server/sonar-search/src/main/java/org/sonar/search/SearchServer.java
server/sonar-server/src/main/java/org/sonar/server/app/EmbeddedTomcat.java
server/sonar-server/src/test/java/org/sonar/server/app/ConnectorsTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/app/LoggingTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/app/NullJarScannerTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/app/WebappTest.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/rule/QProfileDecorator.java
sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java
sonar-core/src/main/java/org/sonar/core/persistence/dialect/DialectUtils.java
sonar-core/src/test/java/org/sonar/core/persistence/dialect/DialectUtilsTest.java

index 6988264f15f216bab40e9e1b92ecf0fce0242fbb..dafb21428d9e0fb63d5705d19f1cae9a1051e734 100644 (file)
@@ -166,8 +166,8 @@ public class SearchServer extends MonitoredProcess {
       .addMapping("_default_", "{\"dynamic\": \"strict\"}")
       .get();
 
-    if (this.isBlocking) {
-      while (node != null && !node.isClosed()) {
+    if (isBlocking) {
+      while (!node.isClosed()) {
         try {
           Thread.sleep(100);
         } catch (InterruptedException e) {
index 8a80a6c05ec439a973e07910cf37a267bd8b0dfa..2356ff340e887eb8ab1e5b4915fa1fa29ba089ce 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.server.app;
 
-import org.apache.catalina.connector.Connector;
 import org.apache.catalina.core.StandardContext;
 import org.apache.catalina.startup.Tomcat;
 import org.apache.commons.io.FileUtils;
@@ -87,14 +86,6 @@ class EmbeddedTomcat implements Terminable {
     return ready && tomcat != null;
   }
 
-  int port() {
-    Connector[] connectors = tomcat.getService().findConnectors();
-    if (connectors.length > 0) {
-      return connectors[0].getLocalPort();
-    }
-    return -1;
-  }
-
   @Override
   public void terminate() {
     if (tomcat != null) {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/app/ConnectorsTest.java b/server/sonar-server/src/test/java/org/sonar/server/app/ConnectorsTest.java
new file mode 100644 (file)
index 0000000..bef81bc
--- /dev/null
@@ -0,0 +1,303 @@
+
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.collect.ImmutableMap;
+import org.apache.catalina.connector.Connector;
+import org.apache.catalina.startup.Tomcat;
+import org.junit.Test;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mockito;
+import org.sonar.process.Props;
+
+import java.net.InetAddress;
+import java.util.Map;
+import java.util.Properties;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+public class ConnectorsTest {
+
+  Tomcat tomcat = mock(Tomcat.class, Mockito.RETURNS_DEEP_STUBS);
+
+  // ---- connectors
+
+  @Test
+  public void configure_thread_pool() throws Exception {
+    Properties p = new Properties();
+    p.setProperty("sonar.web.http.minThreads", "2");
+    p.setProperty("sonar.web.http.maxThreads", "30");
+    p.setProperty("sonar.web.http.acceptCount", "20");
+    Props props = new Props(p);
+
+    Connectors.configure(tomcat, props);
+
+    verify(tomcat).setConnector(argThat(new PropertiesMatcher(
+      ImmutableMap.<String, Object>of("minSpareThreads", 2, "maxThreads", 30, "acceptCount", 20)
+      )));
+  }
+
+  @Test
+  public void configure_default_thread_pool() throws Exception {
+    Props props = new Props(new Properties());
+
+    Connectors.configure(tomcat, props);
+
+    verify(tomcat).setConnector(argThat(new PropertiesMatcher(
+      ImmutableMap.<String, Object>of("minSpareThreads", 5, "maxThreads", 50, "acceptCount", 25)
+      )));
+  }
+
+  @Test
+  public void different_thread_pools_for_connectors() throws Exception {
+    Properties p = new Properties();
+    p.setProperty("sonar.web.port", "9000");
+    p.setProperty("sonar.web.http.minThreads", "2");
+    p.setProperty("sonar.web.https.port", "9443");
+    p.setProperty("sonar.web.https.minThreads", "5");
+    Props props = new Props(p);
+
+    Connectors.configure(tomcat, props);
+
+    verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getPort() == 9000 && c.getProperty("minSpareThreads").equals(2);
+      }
+    }));
+    verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getPort() == 9443 && c.getProperty("minSpareThreads").equals(5);
+      }
+    }));
+  }
+
+  @Test
+  public void fail_if_http_connectors_are_disabled() {
+    Properties p = new Properties();
+    p.setProperty("sonar.web.port", "-1");
+    p.setProperty("sonar.web.https.port", "-1");
+    Props props = new Props(p);
+
+    try {
+      Connectors.configure(tomcat, props);
+      fail();
+    } catch (IllegalStateException e) {
+      assertThat(e.getMessage()).isEqualTo("HTTP connectors are disabled");
+    }
+  }
+
+  @Test
+  public void only_https_is_enabled() {
+    Properties p = new Properties();
+    p.setProperty("sonar.web.port", "-1");
+    p.setProperty("sonar.web.https.port", "9443");
+    Props props = new Props(p);
+
+    Connectors.configure(tomcat, props);
+
+    verify(tomcat).setConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getScheme().equals("https") && c.getPort() == 9443
+          && c.getProperty("clientAuth").equals("false");
+      }
+    }));
+  }
+
+  @Test
+  public void all_connectors_are_enabled() {
+    Properties p = new Properties();
+    p.setProperty("sonar.web.port", "9000");
+    p.setProperty("sonar.ajp.port", "9009");
+    p.setProperty("sonar.web.https.port", "9443");
+    Props props = new Props(p);
+
+    Connectors.configure(tomcat, props);
+
+    verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getScheme().equals("http") && c.getPort() == 9000 && c.getProtocol().equals(Connectors.HTTP_PROTOCOL);
+      }
+    }));
+    verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getScheme().equals("http") && c.getPort() == 9009 && c.getProtocol().equals(Connectors.AJP_PROTOCOL);
+      }
+    }));
+    verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getScheme().equals("https") && c.getPort() == 9443 && c.getProtocol().equals(Connectors.HTTP_PROTOCOL);
+      }
+    }));
+  }
+
+  @Test
+  public void http_and_ajp_and_https_ports_should_be_different() throws Exception {
+    Properties p = new Properties();
+    p.setProperty("sonar.web.port", "9000");
+    p.setProperty("sonar.ajp.port", "9000");
+    p.setProperty("sonar.web.https.port", "9000");
+
+    try {
+      Connectors.configure(tomcat, new Props(p));
+      fail();
+    } catch (IllegalStateException e) {
+      assertThat(e).hasMessage("HTTP, AJP and HTTPS must not use the same port 9000");
+    }
+  }
+
+  @Test
+  public void bind_to_all_addresses_by_default() throws Exception {
+    Properties p = new Properties();
+    p.setProperty("sonar.web.port", "9000");
+    p.setProperty("sonar.ajp.port", "9009");
+    p.setProperty("sonar.web.https.port", "9443");
+
+    Connectors.configure(tomcat, new Props(p));
+
+    verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getScheme().equals("http") && c.getPort() == 9000 && ((InetAddress) c.getProperty("address")).getHostAddress().equals("0.0.0.0");
+      }
+    }));
+    verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getScheme().equals("http") && c.getPort() == 9009 && ((InetAddress) c.getProperty("address")).getHostAddress().equals("0.0.0.0");
+      }
+    }));
+    verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getScheme().equals("https") && c.getPort() == 9443 && ((InetAddress) c.getProperty("address")).getHostAddress().equals("0.0.0.0");
+      }
+    }));
+  }
+
+  @Test
+  public void bind_to_specific_address() throws Exception {
+    Properties p = new Properties();
+    p.setProperty("sonar.web.port", "9000");
+    p.setProperty("sonar.web.https.port", "9443");
+    p.setProperty("sonar.web.host", "1.2.3.4");
+
+    Connectors.configure(tomcat, new Props(p));
+
+    verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getScheme().equals("http") && c.getPort() == 9000 && ((InetAddress) c.getProperty("address")).getHostAddress().equals("1.2.3.4");
+      }
+    }));
+    verify(tomcat.getService()).addConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getScheme().equals("https") && c.getPort() == 9443 && ((InetAddress) c.getProperty("address")).getHostAddress().equals("1.2.3.4");
+      }
+    }));
+  }
+
+  @Test
+  public void enable_client_auth() throws Exception {
+
+    Properties p = new Properties();
+
+    p.setProperty("sonar.web.port", "-1");
+    p.setProperty("sonar.web.https.port", "9443");
+    p.setProperty("sonar.web.https.clientAuth", "want");
+
+    Props props = new Props(p);
+
+    Connectors.configure(tomcat, props);
+
+    verify(tomcat).setConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getScheme().equals("https") && c.getProperty("clientAuth").equals("want");
+      }
+    }));
+  }
+
+  @Test
+  public void require_client_auth() throws Exception {
+
+    Properties p = new Properties();
+
+    p.setProperty("sonar.web.port", "-1");
+    p.setProperty("sonar.web.https.port", "9443");
+    p.setProperty("sonar.web.https.clientAuth", "true");
+
+    Props props = new Props(p);
+
+    Connectors.configure(tomcat, props);
+
+    verify(tomcat).setConnector(argThat(new ArgumentMatcher<Connector>() {
+      @Override
+      public boolean matches(Object o) {
+        Connector c = (Connector) o;
+        return c.getScheme().equals("https") && c.getProperty("clientAuth").equals("true");
+      }
+    }));
+  }
+
+  private static class PropertiesMatcher extends ArgumentMatcher<Connector> {
+    private final Map<String, Object> expected;
+
+    PropertiesMatcher(Map<String, Object> expected) {
+      this.expected = expected;
+    }
+
+    public boolean matches(Object o) {
+      Connector c = (Connector) o;
+      for (Map.Entry<String, Object> entry : expected.entrySet()) {
+        if (!entry.getValue().equals(c.getProperty(entry.getKey()))) {
+          return false;
+        }
+      }
+      return true;
+    }
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/app/LoggingTest.java b/server/sonar-server/src/test/java/org/sonar/server/app/LoggingTest.java
new file mode 100644 (file)
index 0000000..2bc4665
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 ch.qos.logback.access.tomcat.LogbackValve;
+import org.apache.catalina.Lifecycle;
+import org.apache.catalina.LifecycleEvent;
+import org.apache.catalina.Valve;
+import org.apache.catalina.startup.Tomcat;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mockito;
+import org.slf4j.Logger;
+import org.sonar.process.Props;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Properties;
+
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+public class LoggingTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  @Before
+  public void setHome() throws IOException {
+    File homeDir = temp.newFolder("home");
+    System.setProperty("SONAR_HOME", homeDir.getAbsolutePath());
+  }
+
+  @Test
+  public void enable_access_logs_by_Default() throws Exception {
+    Tomcat tomcat = mock(Tomcat.class, Mockito.RETURNS_DEEP_STUBS);
+    Props props = new Props(new Properties());
+    props.set("sonar.path.web", temp.newFolder().getAbsolutePath());
+    Logging.configure(tomcat, props);
+
+    verify(tomcat.getHost().getPipeline()).addValve(argThat(new ArgumentMatcher<Valve>() {
+      @Override
+      public boolean matches(Object o) {
+        LogbackValve v = (LogbackValve) o;
+        String confFile = v.getFilename();
+        return confFile.endsWith("logback-access.xml");
+      }
+    }));
+  }
+
+  @Test
+  public void log_when_started_and_stopped() {
+    Logger logger = mock(Logger.class);
+    Logging.LifecycleLogger listener = new Logging.LifecycleLogger(logger);
+
+    LifecycleEvent event = new LifecycleEvent(mock(Lifecycle.class), "before_init", null);
+    listener.lifecycleEvent(event);
+    verifyZeroInteractions(logger);
+
+    event = new LifecycleEvent(mock(Lifecycle.class), "after_start", null);
+    listener.lifecycleEvent(event);
+    verify(logger).info("Web server is started");
+
+    event = new LifecycleEvent(mock(Lifecycle.class), "after_destroy", null);
+    listener.lifecycleEvent(event);
+    verify(logger).info("Web server is stopped");
+  }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/app/NullJarScannerTest.java b/server/sonar-server/src/test/java/org/sonar/server/app/NullJarScannerTest.java
new file mode 100644 (file)
index 0000000..8977185
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.
+ */
+
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 org.apache.tomcat.JarScannerCallback;
+import org.junit.Test;
+
+import javax.servlet.ServletContext;
+
+import java.util.HashSet;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+public class NullJarScannerTest {
+  @Test
+  public void does_nothing() {
+    ServletContext context = mock(ServletContext.class);
+    ClassLoader classloader = mock(ClassLoader.class);
+    JarScannerCallback callback = mock(JarScannerCallback.class);
+    new NullJarScanner().scan(context, classloader, callback, new HashSet<String>());
+    verifyZeroInteractions(context, classloader, callback);
+  }
+}
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/WebappTest.java
new file mode 100644 (file)
index 0000000..27dbdc6
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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 org.apache.catalina.Context;
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.startup.Tomcat;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.process.Props;
+
+import java.io.File;
+import java.util.Properties;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class WebappTest {
+
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+
+  Props props = new 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");
+    }
+  }
+
+  @Test
+  public void configure_context() throws Exception {
+    props.set("foo", "bar");
+    StandardContext context = mock(StandardContext.class);
+    Tomcat tomcat = mock(Tomcat.class);
+    when(tomcat.addWebapp(anyString(), anyString())).thenReturn(context);
+
+    Webapp.configure(tomcat, props);
+
+    // configure webapp with properties
+    verify(context).addParameter("foo", "bar");
+  }
+
+  @Test
+  public void configure_rails_dev_mode() throws Exception {
+    props.set("sonar.web.dev", "true");
+    Context context = mock(Context.class);
+
+    Webapp.configureRails(props, context);
+
+    verify(context).addParameter("jruby.max.runtimes", "3");
+    verify(context).addParameter("rails.env", "development");
+  }
+
+  @Test
+  public void configure_production_mode() throws Exception {
+    props.set("sonar.web.dev", "false");
+    Context context = mock(Context.class);
+
+    Webapp.configureRails(props, context);
+
+    verify(context).addParameter("jruby.max.runtimes", "1");
+    verify(context).addParameter("rails.env", "production");
+  }
+
+  @Test
+  public void context_path_must_start_with_slash() throws Exception {
+    Properties p = new Properties();
+    p.setProperty("sonar.web.context", "foo");
+
+    try {
+      Webapp.getContextPath(new Props(p));
+      fail();
+    } catch (IllegalStateException e) {
+      assertThat(e.getMessage()).isEqualTo("Value of 'sonar.web.context' must start with a forward slash: 'foo'");
+    }
+  }
+
+  @Test
+  public void root_context_path_must_be_blank() throws Exception {
+    Properties p = new Properties();
+    p.setProperty("sonar.web.context", "/");
+
+    assertThat(Webapp.getContextPath(new Props(p))).isEqualTo("");
+  }
+
+  @Test
+  public void default_context_path_is_root() throws Exception {
+    String context = Webapp.getContextPath(new Props(new Properties()));
+    assertThat(context).isEqualTo("");
+  }
+}
index 9c255f2a13eddcef4224069178dfa46d69690345..9ebc5db46240fd52f76b09860bb406847014c977 100644 (file)
@@ -50,8 +50,11 @@ public class QProfileDecorator implements Decorator {
     }
     UsedQProfiles used = new UsedQProfiles();
     for (Measure childProfilesMeasure : context.getChildrenMeasures(CoreMetrics.QUALITY_PROFILES)) {
-      UsedQProfiles childProfiles = UsedQProfiles.fromJson(childProfilesMeasure.getData());
-      used.add(childProfiles);
+      String data = childProfilesMeasure.getData();
+      if (data != null) {
+        UsedQProfiles childProfiles = UsedQProfiles.fromJson(data);
+        used.add(childProfiles);
+      }
     }
 
     Measure detailsMeasure = new Measure(CoreMetrics.QUALITY_PROFILES, used.toJson());
index 063dd30917ec9c11a03c8940ec42e308ba5591d0..d8a0dadc24b532ca56e7032be49e188d6b4474b8 100644 (file)
@@ -94,9 +94,6 @@ public class DefaultDatabase implements Database {
     doCompleteProperties(properties);
 
     dialect = DialectUtils.find(properties.getProperty(SONAR_JDBC_DIALECT), properties.getProperty(SONAR_JDBC_URL));
-    if (dialect == null) {
-      throw new IllegalStateException(String.format("Can not guess the JDBC dialect. Please check the property %s.", SONAR_JDBC_URL));
-    }
     properties.setProperty(DatabaseProperties.PROP_DRIVER, dialect.getDefaultDriverClassName());
   }
 
index 1ad06d5441563b54721ebbb3c34a8f011ff755e4..8beadff736e3d01e6e8cb9d61200473a84ca7711 100644 (file)
@@ -22,10 +22,11 @@ package org.sonar.core.persistence.dialect;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Iterators;
 import org.apache.commons.lang.StringUtils;
-import org.sonar.api.utils.SonarException;
+import org.sonar.api.utils.MessageException;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
+
 import java.util.NoSuchElementException;
 
 public final class DialectUtils {
@@ -39,7 +40,7 @@ public final class DialectUtils {
   public static Dialect find(final String dialectId, final String jdbcConnectionUrl) {
     Dialect match = StringUtils.isNotBlank(dialectId) ? findById(dialectId) : findByJdbcUrl(jdbcConnectionUrl);
     if (match == null) {
-      throw new SonarException("Unable to determine database dialect to use within sonar with dialect " + dialectId + " jdbc url " + jdbcConnectionUrl);
+      throw MessageException.of("Unable to determine database dialect to use within sonar with dialect " + dialectId + " jdbc url " + jdbcConnectionUrl);
     }
     return match;
   }
index 31d883450e80867043abdd0315e161f2bf83b757..d0c90b2765039bc0edef3e29abb118c77083ec27 100644 (file)
@@ -20,7 +20,7 @@
 package org.sonar.core.persistence.dialect;
 
 import org.junit.Test;
-import org.sonar.api.utils.SonarException;
+import org.sonar.api.utils.MessageException;
 
 import static org.fest.assertions.Assertions.assertThat;
 
@@ -38,7 +38,7 @@ public class DialectUtilsTest {
     assertThat(d).isInstanceOf(MySql.class);
   }
 
-  @Test(expected = SonarException.class)
+  @Test(expected = MessageException.class)
   public void testFindNoMatch() {
     DialectUtils.find("foo", "bar");
   }