aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sonar-application/pom.xml18
-rw-r--r--sonar-application/src/main/assembly/conf/sonar.properties2
-rw-r--r--sonar-application/src/main/java/org/sonar/application/AesCipher.java138
-rw-r--r--sonar-application/src/main/java/org/sonar/application/Base64Cipher.java35
-rw-r--r--sonar-application/src/main/java/org/sonar/application/Cipher.java26
-rw-r--r--sonar-application/src/main/java/org/sonar/application/ConfigurationUtils.java (renamed from sonar-core/src/main/java/org/sonar/core/config/ConfigurationUtils.java)43
-rw-r--r--sonar-application/src/main/java/org/sonar/application/EmbeddedTomcat.java1
-rw-r--r--sonar-application/src/main/java/org/sonar/application/Encryption.java66
-rw-r--r--sonar-application/src/main/java/org/sonar/application/Props.java33
-rw-r--r--sonar-application/src/test/java/org/sonar/application/AesCipherTest.java186
-rw-r--r--sonar-application/src/test/java/org/sonar/application/ConfigurationUtilsTest.java (renamed from sonar-core/src/test/java/org/sonar/core/config/ConfigurationUtilsTest.java)20
-rw-r--r--sonar-application/src/test/java/org/sonar/application/EncryptionTest.java59
-rw-r--r--sonar-application/src/test/java/org/sonar/application/PropsTest.java10
-rw-r--r--sonar-application/src/test/resources/org/sonar/application/AesCipherTest/aes_secret_key.txt1
-rw-r--r--sonar-application/src/test/resources/org/sonar/application/AesCipherTest/bad_secret_key.txt1
-rw-r--r--sonar-application/src/test/resources/org/sonar/application/AesCipherTest/non_trimmed_secret_key.txt3
-rw-r--r--sonar-application/src/test/resources/org/sonar/application/AesCipherTest/other_secret_key.txt1
-rw-r--r--sonar-application/src/test/resources/org/sonar/application/PropsTest/sonar.properties1
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerMetadata.java16
-rw-r--r--sonar-plugin-api/pom.xml11
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java7
-rw-r--r--sonar-plugin-api/src/main/resources/sq-version.txt1
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java38
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/Platform.java9
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/PlatformServletContextListener.java2
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/ServerImpl.java52
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/ServerSettings.java52
-rw-r--r--sonar-server/src/main/java/org/sonar/server/platform/SonarHome.java17
-rw-r--r--sonar-server/src/main/java/org/sonar/server/plugins/BatchResourcesServlet.java14
-rw-r--r--sonar-server/src/main/java/org/sonar/server/source/CodeColorizers.java8
-rw-r--r--sonar-server/src/main/java/org/sonar/server/startup/GenerateBootstrapIndex.java44
-rw-r--r--sonar-server/src/main/java/org/sonar/server/startup/GwtPublisher.java19
-rw-r--r--sonar-server/src/main/java/org/sonar/server/startup/RegisterDashboards.java7
-rw-r--r--sonar-server/src/main/java/org/sonar/server/startup/RegisterMetrics.java7
-rw-r--r--sonar-server/src/main/java/org/sonar/server/startup/RegisterNewMeasureFilters.java7
-rw-r--r--sonar-server/src/main/java/org/sonar/server/text/MacroInterpreter.java6
-rw-r--r--sonar-server/src/test/java/org/sonar/server/platform/PersistentSettingsTest.java6
-rw-r--r--sonar-server/src/test/java/org/sonar/server/platform/ServerImplTest.java59
-rw-r--r--sonar-server/src/test/java/org/sonar/server/platform/ServerLifecycleNotifierTest.java18
-rw-r--r--sonar-server/src/test/java/org/sonar/server/platform/ServerSettingsTest.java46
-rw-r--r--sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginJarsInstallerTest.java5
-rw-r--r--sonar-server/src/test/java/org/sonar/server/startup/GenerateBootstrapIndexTest.java35
-rw-r--r--sonar-server/src/test/java/org/sonar/server/startup/GwtPublisherTest.java1
-rw-r--r--sonar-server/src/test/java/org/sonar/server/text/MacroInterpreterTest.java9
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/platform/PersistentSettingsTest/conf/sonar.properties1
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/empty-version.txt0
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-with-empty-version.properties5
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-with-version.properties5
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-without-version.properties4
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/version.txt1
-rw-r--r--sonar-server/src/test/resources/org/sonar/server/platform/ServerSettingsTest/conf/sonar.properties3
51 files changed, 867 insertions, 292 deletions
diff --git a/sonar-application/pom.xml b/sonar-application/pom.xml
index 3f6a630951b..34c0f89f99a 100644
--- a/sonar-application/pom.xml
+++ b/sonar-application/pom.xml
@@ -17,15 +17,27 @@
<dependencies>
<dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+ <dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+ <dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
@@ -201,12 +213,6 @@
<artifactId>http-request</artifactId>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <scope>test</scope>
- </dependency>
-
</dependencies>
<build>
diff --git a/sonar-application/src/main/assembly/conf/sonar.properties b/sonar-application/src/main/assembly/conf/sonar.properties
index 6c058aa3227..65954622bb9 100644
--- a/sonar-application/src/main/assembly/conf/sonar.properties
+++ b/sonar-application/src/main/assembly/conf/sonar.properties
@@ -82,7 +82,7 @@ sonar.jdbc.timeBetweenEvictionRunsMillis=30000
# Web context. When set, it must start with forward slash (for example /sonarqube).
# The default value is root context (empty value).
-#sonar.web.context=
+#sonar.web.context=/
# TCP port for incoming HTTP connections. Disabled when value is -1.
#sonar.web.port=9000
diff --git a/sonar-application/src/main/java/org/sonar/application/AesCipher.java b/sonar-application/src/main/java/org/sonar/application/AesCipher.java
new file mode 100644
index 00000000000..d006146a7e6
--- /dev/null
+++ b/sonar-application/src/main/java/org/sonar/application/AesCipher.java
@@ -0,0 +1,138 @@
+/*
+ * 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.application;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Throwables;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+
+import javax.annotation.Nullable;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.Key;
+import java.security.SecureRandom;
+
+final class AesCipher extends Cipher {
+
+ // Can't be increased because of Java 6 policy files :
+ // https://confluence.terena.org/display/~visser/No+256+bit+ciphers+for+Java+apps
+ // http://java.sun.com/javase/6/webnotes/install/jre/README
+ public static final int KEY_SIZE_IN_BITS = 128;
+
+ private static final String CRYPTO_KEY = "AES";
+
+ /**
+ * Duplication from CoreProperties.ENCRYPTION_SECRET_KEY_PATH
+ */
+ private static final String ENCRYPTION_SECRET_KEY_PATH = "sonar.secretKeyPath";
+
+ private String pathToSecretKey;
+
+ AesCipher(@Nullable String pathToSecretKey) {
+ this.pathToSecretKey = pathToSecretKey;
+ }
+
+ @Override
+ String encrypt(String clearText) {
+ try {
+ javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CRYPTO_KEY);
+ cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, loadSecretFile());
+ return new String(Base64.encodeBase64(cipher.doFinal(clearText.getBytes("UTF-8"))));
+ } catch (Exception e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ @Override
+ String decrypt(String encryptedText) {
+ try {
+ javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(CRYPTO_KEY);
+ cipher.init(javax.crypto.Cipher.DECRYPT_MODE, loadSecretFile());
+ byte[] cipherData = cipher.doFinal(Base64.decodeBase64(StringUtils.trim(encryptedText)));
+ return new String(cipherData);
+ } catch (Exception e) {
+ throw Throwables.propagate(e);
+ }
+ }
+
+ /**
+ * This method checks the existence of the file, but not the validity of the contained key.
+ */
+ boolean hasSecretKey() {
+ String path = getPathToSecretKey();
+ if (StringUtils.isNotBlank(path)) {
+ File file = new File(path);
+ return file.exists() && file.isFile();
+ }
+ return false;
+ }
+
+ private Key loadSecretFile() throws IOException {
+ String path = getPathToSecretKey();
+ return loadSecretFileFromFile(path);
+ }
+
+ @VisibleForTesting
+ Key loadSecretFileFromFile(@Nullable String path) throws IOException {
+ if (StringUtils.isBlank(path)) {
+ throw new IllegalStateException("Secret key not found. Please set the property " + ENCRYPTION_SECRET_KEY_PATH);
+ }
+ File file = new File(path);
+ if (!file.exists() || !file.isFile()) {
+ throw new IllegalStateException("The property " + ENCRYPTION_SECRET_KEY_PATH + " does not link to a valid file: " + path);
+ }
+ String s = FileUtils.readFileToString(file);
+ if (StringUtils.isBlank(s)) {
+ throw new IllegalStateException("No secret key in the file: " + path);
+ }
+ return new SecretKeySpec(Base64.decodeBase64(StringUtils.trim(s)), CRYPTO_KEY);
+ }
+
+ String generateRandomSecretKey() {
+ try {
+ KeyGenerator keyGen = KeyGenerator.getInstance(CRYPTO_KEY);
+ keyGen.init(KEY_SIZE_IN_BITS, new SecureRandom());
+ SecretKey secretKey = keyGen.generateKey();
+ return new String(Base64.encodeBase64(secretKey.getEncoded()));
+
+ } catch (Exception e) {
+ throw new IllegalStateException("Fail to generate secret key", e);
+ }
+ }
+
+ @VisibleForTesting
+ String getPathToSecretKey() {
+ if (StringUtils.isBlank(pathToSecretKey)) {
+ pathToSecretKey = new File(FileUtils.getUserDirectoryPath(), ".sonar/sonar-secret.txt").getPath();
+ }
+ return pathToSecretKey;
+ }
+
+ public void setPathToSecretKey(@Nullable String pathToSecretKey) {
+ this.pathToSecretKey = pathToSecretKey;
+ }
+}
diff --git a/sonar-application/src/main/java/org/sonar/application/Base64Cipher.java b/sonar-application/src/main/java/org/sonar/application/Base64Cipher.java
new file mode 100644
index 00000000000..5abbeb85ac2
--- /dev/null
+++ b/sonar-application/src/main/java/org/sonar/application/Base64Cipher.java
@@ -0,0 +1,35 @@
+/*
+ * 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.application;
+
+import org.apache.commons.codec.binary.Base64;
+
+final class Base64Cipher extends Cipher {
+ @Override
+ String encrypt(String clearText) {
+ return new String(Base64.encodeBase64(clearText.getBytes()));
+ }
+
+ @Override
+ String decrypt(String encryptedText) {
+ return new String(Base64.decodeBase64(encryptedText));
+ }
+}
diff --git a/sonar-application/src/main/java/org/sonar/application/Cipher.java b/sonar-application/src/main/java/org/sonar/application/Cipher.java
new file mode 100644
index 00000000000..44abfbb3176
--- /dev/null
+++ b/sonar-application/src/main/java/org/sonar/application/Cipher.java
@@ -0,0 +1,26 @@
+/*
+ * 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.application;
+
+abstract class Cipher {
+ abstract String encrypt(String clearText);
+ abstract String decrypt(String encryptedText);
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/config/ConfigurationUtils.java b/sonar-application/src/main/java/org/sonar/application/ConfigurationUtils.java
index d3875f78846..a5a563a168c 100644
--- a/sonar-core/src/main/java/org/sonar/core/config/ConfigurationUtils.java
+++ b/sonar-application/src/main/java/org/sonar/application/ConfigurationUtils.java
@@ -17,60 +17,25 @@
* 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.core.config;
+package org.sonar.application;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.text.StrSubstitutor;
-import javax.annotation.WillClose;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
-/**
- * @since 2.12
- */
public final class ConfigurationUtils {
private ConfigurationUtils() {
+ // Utility class
}
- public static void copyProperties(Properties from, Map<String, String> to) {
- for (Map.Entry<Object, Object> entry : from.entrySet()) {
- String key = (String) entry.getKey();
- to.put(key, entry.getValue().toString());
- }
- }
-
- public static Properties openProperties(File file) throws IOException {
- FileInputStream input = FileUtils.openInputStream(file);
- return readInputStream(input);
- }
-
- /**
- * Note that the input stream is closed in this method.
- */
- public static Properties readInputStream(@WillClose InputStream input) throws IOException {
- try {
- Properties p = new Properties();
- p.load(input);
- return p;
-
- } finally {
- IOUtils.closeQuietly(input);
- }
- }
-
- public static Properties interpolateEnvVariables(Properties properties) {
+ static Properties interpolateEnvVariables(Properties properties) {
return interpolateVariables(properties, System.getenv());
}
- public static Properties interpolateVariables(Properties properties, Map<String, String> variables) {
+ static Properties interpolateVariables(Properties properties, Map<String, String> variables) {
Properties result = new Properties();
Enumeration keys = properties.keys();
while (keys.hasMoreElements()) {
diff --git a/sonar-application/src/main/java/org/sonar/application/EmbeddedTomcat.java b/sonar-application/src/main/java/org/sonar/application/EmbeddedTomcat.java
index ddb1efad898..a677f8bcf11 100644
--- a/sonar-application/src/main/java/org/sonar/application/EmbeddedTomcat.java
+++ b/sonar-application/src/main/java/org/sonar/application/EmbeddedTomcat.java
@@ -65,6 +65,7 @@ class EmbeddedTomcat {
tomcat.getHost().setDeployOnStartup(true);
Props props = Props.create(env);
+
Logging.configure(tomcat, env, props);
Connectors.configure(tomcat, props);
Webapp.configure(tomcat, env, props);
diff --git a/sonar-application/src/main/java/org/sonar/application/Encryption.java b/sonar-application/src/main/java/org/sonar/application/Encryption.java
new file mode 100644
index 00000000000..60e732fc716
--- /dev/null
+++ b/sonar-application/src/main/java/org/sonar/application/Encryption.java
@@ -0,0 +1,66 @@
+/*
+ * 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.application;
+
+import com.google.common.collect.ImmutableMap;
+
+import javax.annotation.Nullable;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @since 3.0
+ */
+public final class Encryption {
+
+ private static final String BASE64_ALGORITHM = "b64";
+
+ private static final String AES_ALGORITHM = "aes";
+ private final AesCipher aesCipher;
+
+ private final Map<String, Cipher> ciphers;
+ private static final Pattern ENCRYPTED_PATTERN = Pattern.compile("\\{(.*?)\\}(.*)");
+
+ public Encryption(@Nullable String pathToSecretKey) {
+ aesCipher = new AesCipher(pathToSecretKey);
+ ciphers = ImmutableMap.of(
+ BASE64_ALGORITHM, new Base64Cipher(),
+ AES_ALGORITHM, aesCipher);
+ }
+ public boolean isEncrypted(String value) {
+ return value.indexOf('{') == 0 && value.indexOf('}') > 1;
+ }
+
+ public String decrypt(String encryptedText) {
+ Matcher matcher = ENCRYPTED_PATTERN.matcher(encryptedText);
+ if (matcher.matches()) {
+ Cipher cipher = ciphers.get(matcher.group(1).toLowerCase(Locale.ENGLISH));
+ if (cipher != null) {
+ return cipher.decrypt(matcher.group(2));
+ }
+ }
+ return encryptedText;
+ }
+
+}
diff --git a/sonar-application/src/main/java/org/sonar/application/Props.java b/sonar-application/src/main/java/org/sonar/application/Props.java
index 7b33d918cc6..51a6cdfe49e 100644
--- a/sonar-application/src/main/java/org/sonar/application/Props.java
+++ b/sonar-application/src/main/java/org/sonar/application/Props.java
@@ -22,16 +22,14 @@ package org.sonar.application;
import org.apache.commons.io.IOUtils;
import javax.annotation.Nullable;
+
import java.io.File;
-import java.io.FileNotFoundException;
import java.io.FileReader;
-import java.io.IOException;
+import java.util.Map;
import java.util.Properties;
-/**
- * TODO support env substitution and encryption
- */
class Props {
+
private final Properties props;
Props(Properties props) {
@@ -80,8 +78,18 @@ class Props {
FileReader reader = null;
try {
reader = new FileReader(propsFile);
+
+ // order is important : the last override the first
p.load(reader);
+ p.putAll(System.getenv());
p.putAll(System.getProperties());
+
+ p = ConfigurationUtils.interpolateEnvVariables(p);
+ p = decrypt(p);
+
+ // Set all properties as system properties to pass them to PlatformServletContextListener
+ System.setProperties(p);
+
return new Props(p);
} catch (Exception e) {
@@ -91,4 +99,19 @@ class Props {
IOUtils.closeQuietly(reader);
}
}
+
+ static Properties decrypt(Properties properties) {
+ Encryption encryption = new Encryption(null);
+ Properties result = new Properties();
+
+ for (Map.Entry<Object, Object> entry : properties.entrySet()) {
+ String key = (String) entry.getKey();
+ String value = (String) entry.getValue();
+ if (encryption.isEncrypted(value)) {
+ value = encryption.decrypt(value);
+ }
+ result.setProperty(key, value);
+ }
+ return result;
+ }
}
diff --git a/sonar-application/src/test/java/org/sonar/application/AesCipherTest.java b/sonar-application/src/test/java/org/sonar/application/AesCipherTest.java
new file mode 100644
index 00000000000..9f097093105
--- /dev/null
+++ b/sonar-application/src/test/java/org/sonar/application/AesCipherTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.application;
+
+import com.google.common.io.Resources;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang.StringUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import javax.crypto.BadPaddingException;
+
+import java.io.File;
+import java.security.InvalidKeyException;
+import java.security.Key;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+
+public class AesCipherTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void generateRandomSecretKey() {
+ AesCipher cipher = new AesCipher(null);
+
+ String key = cipher.generateRandomSecretKey();
+
+ assertThat(StringUtils.isNotBlank(key)).isTrue();
+ assertThat(Base64.isArrayByteBase64(key.getBytes())).isTrue();
+ }
+
+ @Test
+ public void encrypt() throws Exception {
+ AesCipher cipher = new AesCipher(pathToSecretKey());
+
+ String encryptedText = cipher.encrypt("this is a secret");
+
+ assertThat(StringUtils.isNotBlank(encryptedText)).isTrue();
+ assertThat(Base64.isArrayByteBase64(encryptedText.getBytes())).isTrue();
+ }
+
+ @Test
+ public void encrypt_bad_key() throws Exception {
+ thrown.expect(RuntimeException.class);
+ thrown.expectMessage("Invalid AES key");
+
+ AesCipher cipher = new AesCipher(getPath("bad_secret_key.txt"));
+
+ cipher.encrypt("this is a secret");
+ }
+
+ @Test
+ public void decrypt() throws Exception {
+ AesCipher cipher = new AesCipher(pathToSecretKey());
+
+ // the following value has been encrypted with the key /org/sonar/api/config/AesCipherTest/aes_secret_key.txt
+ String clearText = cipher.decrypt("9mx5Zq4JVyjeChTcVjEide4kWCwusFl7P2dSVXtg9IY=");
+
+ assertThat(clearText).isEqualTo("this is a secret");
+ }
+
+ @Test
+ public void decrypt_bad_key() throws Exception {
+ AesCipher cipher = new AesCipher(getPath("bad_secret_key.txt"));
+
+ try {
+ cipher.decrypt("9mx5Zq4JVyjeChTcVjEide4kWCwusFl7P2dSVXtg9IY=");
+ fail();
+
+ } catch (RuntimeException e) {
+ assertThat(e.getCause()).isInstanceOf(InvalidKeyException.class);
+ }
+ }
+
+ @Test
+ public void decrypt_other_key() throws Exception {
+ AesCipher cipher = new AesCipher(getPath("other_secret_key.txt"));
+
+ try {
+ // text encrypted with another key
+ cipher.decrypt("9mx5Zq4JVyjeChTcVjEide4kWCwusFl7P2dSVXtg9IY=");
+ fail();
+
+ } catch (RuntimeException e) {
+ assertThat(e.getCause()).isInstanceOf(BadPaddingException.class);
+ }
+ }
+
+ @Test
+ public void encryptThenDecrypt() throws Exception {
+ AesCipher cipher = new AesCipher(pathToSecretKey());
+
+ assertThat(cipher.decrypt(cipher.encrypt("foo"))).isEqualTo("foo");
+ }
+
+ @Test
+ public void testDefaultPathToSecretKey() {
+ AesCipher cipher = new AesCipher(null);
+
+ String path = cipher.getPathToSecretKey();
+
+ assertThat(StringUtils.isNotBlank(path)).isTrue();
+ assertThat(new File(path).getName()).isEqualTo("sonar-secret.txt");
+ }
+
+ @Test
+ public void loadSecretKeyFromFile() throws Exception {
+ AesCipher cipher = new AesCipher(null);
+ Key secretKey = cipher.loadSecretFileFromFile(pathToSecretKey());
+ assertThat(secretKey.getAlgorithm()).isEqualTo("AES");
+ assertThat(secretKey.getEncoded().length).isGreaterThan(10);
+ }
+
+ @Test
+ public void loadSecretKeyFromFile_trim_content() throws Exception {
+ String path = getPath("non_trimmed_secret_key.txt");
+ AesCipher cipher = new AesCipher(null);
+
+ Key secretKey = cipher.loadSecretFileFromFile(path);
+
+ assertThat(secretKey.getAlgorithm()).isEqualTo("AES");
+ assertThat(secretKey.getEncoded().length).isGreaterThan(10);
+ }
+
+ @Test
+ public void loadSecretKeyFromFile_file_does_not_exist() throws Exception {
+ thrown.expect(IllegalStateException.class);
+
+ AesCipher cipher = new AesCipher(null);
+ cipher.loadSecretFileFromFile("/file/does/not/exist");
+ }
+
+ @Test
+ public void loadSecretKeyFromFile_no_property() throws Exception {
+ thrown.expect(IllegalStateException.class);
+
+ AesCipher cipher = new AesCipher(null);
+ cipher.loadSecretFileFromFile(null);
+ }
+
+ @Test
+ public void hasSecretKey() throws Exception {
+ AesCipher cipher = new AesCipher(pathToSecretKey());
+
+ assertThat(cipher.hasSecretKey()).isTrue();
+ }
+
+ @Test
+ public void doesNotHaveSecretKey() throws Exception {
+ AesCipher cipher = new AesCipher("/my/twitter/id/is/SimonBrandhof");
+
+ assertThat(cipher.hasSecretKey()).isFalse();
+ }
+
+ private static String getPath(String file){
+ return Resources.getResource(AesCipherTest.class, "AesCipherTest/" + file).getPath();
+ }
+
+ private static String pathToSecretKey() throws Exception {
+ return getPath("aes_secret_key.txt");
+ }
+
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/config/ConfigurationUtilsTest.java b/sonar-application/src/test/java/org/sonar/application/ConfigurationUtilsTest.java
index 92452b2338e..29a722b9fad 100644
--- a/sonar-core/src/test/java/org/sonar/core/config/ConfigurationUtilsTest.java
+++ b/sonar-application/src/test/java/org/sonar/application/ConfigurationUtilsTest.java
@@ -17,7 +17,7 @@
* 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.core.config;
+package org.sonar.application;
import com.google.common.collect.Maps;
import org.junit.Test;
@@ -52,22 +52,4 @@ public class ConfigurationUtilsTest {
assertThat(input.getProperty("do_not_change"), is("${SONAR_JDBC_URL}"));
}
- @Test
- public void shouldCopyProperties() {
- Properties input = new Properties();
- input.setProperty("hello", "world");
- input.setProperty("foo", "bar");
- Map<String, String> output = Maps.newHashMap();
-
- ConfigurationUtils.copyProperties(input, output);
-
- assertThat(output.size(), is(2));
- assertThat(output.get("hello"), is("world"));
- assertThat(output.get("foo"), is("bar"));
-
- // input is not changed
- assertThat(input.size(), is(2));
- assertThat(input.getProperty("hello"), is("world"));
- assertThat(input.getProperty("foo"), is("bar"));
- }
}
diff --git a/sonar-application/src/test/java/org/sonar/application/EncryptionTest.java b/sonar-application/src/test/java/org/sonar/application/EncryptionTest.java
new file mode 100644
index 00000000000..85b3c568a35
--- /dev/null
+++ b/sonar-application/src/test/java/org/sonar/application/EncryptionTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.application;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class EncryptionTest {
+
+ @Test
+ public void isEncrypted() {
+ Encryption encryption = new Encryption(null);
+ assertThat(encryption.isEncrypted("{aes}ADASDASAD"), is(true));
+ assertThat(encryption.isEncrypted("{b64}ADASDASAD"), is(true));
+ assertThat(encryption.isEncrypted("{abc}ADASDASAD"), is(true));
+
+ assertThat(encryption.isEncrypted("{}"), is(false));
+ assertThat(encryption.isEncrypted("{foo"), is(false));
+ assertThat(encryption.isEncrypted("foo{aes}"), is(false));
+ }
+
+ @Test
+ public void decrypt() {
+ Encryption encryption = new Encryption(null);
+ assertThat(encryption.decrypt("{b64}Zm9v"), is("foo"));
+ }
+
+ @Test
+ public void decrypt_unknown_algorithm() {
+ Encryption encryption = new Encryption(null);
+ assertThat(encryption.decrypt("{xxx}Zm9v"), is("{xxx}Zm9v"));
+ }
+
+ @Test
+ public void decrypt_uncrypted_text() {
+ Encryption encryption = new Encryption(null);
+ assertThat(encryption.decrypt("foo"), is("foo"));
+ }
+}
diff --git a/sonar-application/src/test/java/org/sonar/application/PropsTest.java b/sonar-application/src/test/java/org/sonar/application/PropsTest.java
index 92091740301..46ca5e8dd26 100644
--- a/sonar-application/src/test/java/org/sonar/application/PropsTest.java
+++ b/sonar-application/src/test/java/org/sonar/application/PropsTest.java
@@ -19,6 +19,7 @@
*/
package org.sonar.application;
+import com.google.common.io.Resources;
import org.apache.commons.io.FilenameUtils;
import org.junit.Test;
@@ -31,6 +32,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class PropsTest {
+
@Test
public void of() throws Exception {
Properties p = new Properties();
@@ -99,8 +101,10 @@ public class PropsTest {
@Test
public void load_file_and_system_properties() throws Exception {
+ System.setProperty("hello", "bar");
+
Env env = mock(Env.class);
- File propsFile = new File(getClass().getResource("/org/sonar/application/PropsTest/sonar.properties").toURI());
+ File propsFile = new File(Resources.getResource(getClass(), "PropsTest/sonar.properties").getFile());
when(env.file("conf/sonar.properties")).thenReturn(propsFile);
Props props = Props.create(env);
@@ -109,7 +113,11 @@ public class PropsTest {
assertThat(props.of("java.version")).isNotNull();
// system properties override file properties
+ assertThat(props.of("hello")).isEqualTo("bar");
assertThat(props.of("java.io.tmpdir")).isNotEmpty().isNotEqualTo("/should/be/overridden");
+
+ assertThat(System.getProperty("foo")).isEqualTo("bar");
+ assertThat(System.getProperty("hello")).isEqualTo("bar");
}
@Test
diff --git a/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/aes_secret_key.txt b/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/aes_secret_key.txt
new file mode 100644
index 00000000000..65b98c522da
--- /dev/null
+++ b/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/aes_secret_key.txt
@@ -0,0 +1 @@
+0PZz+G+f8mjr3sPn4+AhHg== \ No newline at end of file
diff --git a/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/bad_secret_key.txt b/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/bad_secret_key.txt
new file mode 100644
index 00000000000..b33e179e5c8
--- /dev/null
+++ b/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/bad_secret_key.txt
@@ -0,0 +1 @@
+badbadbad== \ No newline at end of file
diff --git a/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/non_trimmed_secret_key.txt b/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/non_trimmed_secret_key.txt
new file mode 100644
index 00000000000..ab83e4adc03
--- /dev/null
+++ b/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/non_trimmed_secret_key.txt
@@ -0,0 +1,3 @@
+
+ 0PZz+G+f8mjr3sPn4+AhHg==
+
diff --git a/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/other_secret_key.txt b/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/other_secret_key.txt
new file mode 100644
index 00000000000..23f5ecf5104
--- /dev/null
+++ b/sonar-application/src/test/resources/org/sonar/application/AesCipherTest/other_secret_key.txt
@@ -0,0 +1 @@
+IBxEUxZ41c8XTxyaah1Qlg== \ No newline at end of file
diff --git a/sonar-application/src/test/resources/org/sonar/application/PropsTest/sonar.properties b/sonar-application/src/test/resources/org/sonar/application/PropsTest/sonar.properties
index b73be15411b..5c06e58a32e 100644
--- a/sonar-application/src/test/resources/org/sonar/application/PropsTest/sonar.properties
+++ b/sonar-application/src/test/resources/org/sonar/application/PropsTest/sonar.properties
@@ -1,2 +1,3 @@
+hello: world
foo=bar
java.io.tmpdir=/should/be/overridden
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerMetadata.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerMetadata.java
index cf664e315df..01d2b5915c1 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerMetadata.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerMetadata.java
@@ -27,6 +27,7 @@ import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.Server;
+import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -70,6 +71,21 @@ public class ServerMetadata extends Server implements BatchComponent {
}
@Override
+ public File getRootDir() {
+ return null;
+ }
+
+ @Override
+ public File getDeployDir() {
+ return null;
+ }
+
+ @Override
+ public String getContextPath() {
+ return null;
+ }
+
+ @Override
public String getURL() {
return client.getURL();
}
diff --git a/sonar-plugin-api/pom.xml b/sonar-plugin-api/pom.xml
index 74f16c9a01e..2cd8b5bea82 100644
--- a/sonar-plugin-api/pom.xml
+++ b/sonar-plugin-api/pom.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@@ -191,6 +192,14 @@
</executions>
</plugin>
</plugins>
+
+ <resources>
+ <resource>
+ <!-- Used to set SonarQube version in sq-version.txt file -->
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
</build>
</project>
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java
index d6c39401c2d..7fd8afd1b1e 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java
@@ -22,6 +22,7 @@ package org.sonar.api.platform;
import org.sonar.api.BatchComponent;
import org.sonar.api.ServerComponent;
+import java.io.File;
import java.util.Date;
/**
@@ -35,6 +36,12 @@ public abstract class Server implements BatchComponent, ServerComponent {
public abstract Date getStartedAt();
+ public abstract File getRootDir();
+
+ public abstract File getDeployDir();
+
+ public abstract String getContextPath();
+
/**
* @return the server URL when executed from batch, else null.
* @since 2.4
diff --git a/sonar-plugin-api/src/main/resources/sq-version.txt b/sonar-plugin-api/src/main/resources/sq-version.txt
new file mode 100644
index 00000000000..ad96e7cf933
--- /dev/null
+++ b/sonar-plugin-api/src/main/resources/sq-version.txt
@@ -0,0 +1 @@
+${project.version}
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java b/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java
index 473fbd0e8f8..cf7a2d6ac0f 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/DefaultServerFileSystem.java
@@ -21,12 +21,12 @@ package org.sonar.server.platform;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.FileFilterUtils;
-import org.apache.commons.lang.StringUtils;
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;
import org.sonar.core.persistence.Database;
@@ -47,26 +47,22 @@ public class DefaultServerFileSystem implements ServerFileSystem, Startable {
private static final Logger LOGGER = LoggerFactory.getLogger(DefaultServerFileSystem.class);
private Database database;
- private File deployDir;
+ private final Server server;
private File homeDir;
- public DefaultServerFileSystem(Database database, Settings settings) {
+ public DefaultServerFileSystem(Database database, Settings settings, Server server) {
this.database = database;
+ this.server = server;
this.homeDir = new File(settings.getString(CoreProperties.SONAR_HOME));
-
- String deployPath = settings.getString(ServerSettings.DEPLOY_DIR);
- if (StringUtils.isNotBlank(deployPath)) {
- this.deployDir = new File(deployPath);
- }
}
/**
* for unit tests
*/
- public DefaultServerFileSystem(Database database, File homeDir, File deployDir) {
+ public DefaultServerFileSystem(Database database, File homeDir, Server server) {
this.database = database;
- this.deployDir = deployDir;
this.homeDir = homeDir;
+ this.server = server;
}
@Override
@@ -76,19 +72,19 @@ public class DefaultServerFileSystem implements ServerFileSystem, Startable {
throw new IllegalStateException("SonarQube home directory does not exist");
}
- if (deployDir == null) {
- throw new IllegalStateException("The target directory to deploy libraries is not set");
- }
-
try {
- LOGGER.info("Deploy dir: " + deployDir.getAbsolutePath());
- FileUtils.forceMkdir(deployDir);
- for (File subDirectory : deployDir.listFiles((FileFilter) FileFilterUtils.directoryFileFilter())) {
+ 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);
}
} catch (IOException e) {
- throw new IllegalStateException("The following directory can not be created: " + deployDir.getAbsolutePath(), e);
+ throw new IllegalStateException("The following directory can not be created: " + getDeployDir().getAbsolutePath(), e);
}
File deprecated = getDeprecatedPluginsDir();
@@ -117,15 +113,15 @@ public class DefaultServerFileSystem implements ServerFileSystem, Startable {
}
public File getDeployDir() {
- return deployDir;
+ return server.getDeployDir();
}
public File getDeployedJdbcDriverIndex() {
- return new File(deployDir, "jdbc-driver.txt");
+ return new File(getDeployDir(), "jdbc-driver.txt");
}
public File getDeployedPluginsDir() {
- return new File(deployDir, "plugins");
+ return new File(getDeployDir(), "plugins");
}
public File getDownloadedPluginsDir() {
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
index 353893e7d0b..510b3f6f620 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java
@@ -25,7 +25,8 @@ import org.sonar.api.platform.Server;
import org.sonar.core.persistence.DatabaseVersion;
import javax.annotation.CheckForNull;
-import javax.servlet.ServletContext;
+
+import java.util.Properties;
/**
* @since 2.2
@@ -40,7 +41,7 @@ public class Platform {
private boolean dbConnected = false;
private boolean started = false;
- private Platform() {
+ public Platform() {
}
public static Platform getInstance() {
@@ -65,8 +66,8 @@ public class Platform {
return null;
}
- public void init(ServletContext servletContext) {
- serverComponents = new ServerComponents(this, servletContext);
+ public void init(Properties properties) {
+ serverComponents = new ServerComponents(this, properties);
if (!dbConnected) {
startLevel1Container();
startLevel2Container();
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/PlatformServletContextListener.java b/sonar-server/src/main/java/org/sonar/server/platform/PlatformServletContextListener.java
index 6257c03551d..82e2e659596 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/PlatformServletContextListener.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/PlatformServletContextListener.java
@@ -50,7 +50,7 @@ public final class PlatformServletContextListener implements ServletContextListe
public void contextInitialized(ServletContextEvent event) {
try {
configureLogback(event);
- Platform.getInstance().init(event.getServletContext());
+ Platform.getInstance().init(System.getProperties());
Platform.getInstance().doStart();
} catch (Throwable t) {
// Tomcat 7 "limitations":
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/ServerImpl.java b/sonar-server/src/main/java/org/sonar/server/platform/ServerImpl.java
index 79d4e11ac18..8ceb686e0a0 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/ServerImpl.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/ServerImpl.java
@@ -20,7 +20,9 @@
package org.sonar.server.platform;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
+import com.google.common.io.Resources;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.picocontainer.Startable;
@@ -30,8 +32,10 @@ import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.Server;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
@@ -42,21 +46,24 @@ public final class ServerImpl extends Server implements Startable {
private final Settings settings;
private final Date startedAt;
private final String buildProperties;
- private final String pomProperties;
+ private final String versionPath;
private String id;
private String version;
private String implementationBuild;
+ private String contextPath;
+ private File sonarHome;
+ private File deployDir;
public ServerImpl(Settings settings) {
- this(settings, "/build.properties", "/META-INF/maven/org.codehaus.sonar/sonar-plugin-api/pom.properties");
+ this(settings, "/build.properties", "/sq-version.txt");
}
@VisibleForTesting
- ServerImpl(Settings settings, String buildProperties, String pomProperties) {
+ ServerImpl(Settings settings, String buildProperties, String versionPath) {
this.settings = settings;
this.startedAt = new Date();
this.buildProperties = buildProperties;
- this.pomProperties = pomProperties;
+ this.versionPath = versionPath;
}
@Override
@@ -64,13 +71,17 @@ public final class ServerImpl extends Server implements Startable {
try {
id = new SimpleDateFormat("yyyyMMddHHmmss").format(startedAt);
- version = read(pomProperties).getProperty("version", "");
+ version = readVersion(versionPath);
implementationBuild = read(buildProperties).getProperty("Implementation-Build");
+ contextPath = StringUtils.defaultIfBlank(settings.getString("sonar.web.context"), "/");
- if (StringUtils.isBlank(version)) {
- throw new IllegalStateException("Unknown SonarQube version");
+ sonarHome = new File(settings.getString(CoreProperties.SONAR_HOME));
+ if (!sonarHome.isDirectory()) {
+ throw new IllegalStateException("SonarQube home directory is not valid");
}
+ deployDir = new File(sonarHome, "/web/deploy/");
+
LOG.info("SonarQube {}", Joiner.on(" / ").skipNulls().join("Server", version, implementationBuild));
} catch (IOException e) {
@@ -107,6 +118,32 @@ public final class ServerImpl extends Server implements Startable {
return startedAt;
}
+ @Override
+ public File getRootDir() {
+ return sonarHome;
+ }
+
+ @Override
+ public File getDeployDir() {
+ return deployDir;
+ }
+
+ @Override
+ public String getContextPath() {
+ return contextPath;
+ }
+
+ private static String readVersion(String filename) throws IOException {
+ URL url = ServerImpl.class.getResource(filename);
+ if (url != null) {
+ String version = Resources.toString(url, Charsets.UTF_8);
+ if (!StringUtils.isBlank(version)) {
+ return StringUtils.deleteWhitespace(version);
+ }
+ }
+ throw new IllegalStateException("Unknown SonarQube version");
+ }
+
private static Properties read(String filename) throws IOException {
Properties properties = new Properties();
@@ -122,6 +159,7 @@ public final class ServerImpl extends Server implements Startable {
return properties;
}
+
@Override
public String getURL() {
return null;
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/ServerSettings.java b/sonar-server/src/main/java/org/sonar/server/platform/ServerSettings.java
index 81d5116b6dc..21c301b3cfe 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/ServerSettings.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/ServerSettings.java
@@ -19,17 +19,13 @@
*/
package org.sonar.server.platform;
-import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.configuration.Configuration;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.Settings;
-import org.sonar.core.config.ConfigurationUtils;
import javax.annotation.Nullable;
-import javax.servlet.ServletContext;
-import java.io.File;
import java.util.Collections;
import java.util.Map;
import java.util.Properties;
@@ -47,23 +43,14 @@ import java.util.Properties;
*/
public class ServerSettings extends Settings {
- public static final String DEPLOY_DIR = "sonar.web.deployDir";
-
+ private final Properties properties;
private Configuration deprecatedConfiguration;
- private File deployDir;
- private File sonarHome;
-
- public ServerSettings(PropertyDefinitions definitions, Configuration deprecatedConfiguration, ServletContext servletContext) {
- this(definitions, deprecatedConfiguration, getDeployDir(servletContext), SonarHome.getHome());
- }
- @VisibleForTesting
- ServerSettings(PropertyDefinitions definitions, Configuration deprecatedConfiguration, File deployDir, File sonarHome) {
+ public ServerSettings(PropertyDefinitions definitions, Configuration deprecatedConfiguration, Properties properties) {
super(definitions);
this.deprecatedConfiguration = deprecatedConfiguration;
- this.deployDir = deployDir;
- this.sonarHome = sonarHome;
- load(Collections.<String, String> emptyMap());
+ this.properties = properties;
+ load(Collections.<String, String>emptyMap());
// Secret key is loaded from conf/sonar.properties
getEncryption().setPathToSecretKey(getString(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
}
@@ -74,43 +61,14 @@ public class ServerSettings extends Settings {
private ServerSettings load(Map<String, String> databaseSettings) {
clear();
- setProperty(CoreProperties.SONAR_HOME, sonarHome.getAbsolutePath());
- setProperty(DEPLOY_DIR, deployDir.getAbsolutePath());
// order is important : the last override the first
addProperties(databaseSettings);
- loadPropertiesFile(sonarHome);
- addEnvironmentVariables();
- addSystemProperties();
+ addProperties(properties);
return this;
}
- private void loadPropertiesFile(File sonarHome) {
- File propertiesFile = new File(sonarHome, "conf/sonar.properties");
- if (!propertiesFile.isFile() || !propertiesFile.exists()) {
- throw new IllegalStateException("Properties file does not exist: " + propertiesFile);
- }
- try {
- Properties p = ConfigurationUtils.openProperties(propertiesFile);
- addProperties(ConfigurationUtils.interpolateEnvVariables(p));
- } catch (Exception e) {
- throw new IllegalStateException("Fail to load configuration file: " + propertiesFile, e);
- }
- }
-
- static File getDeployDir(ServletContext servletContext) {
- String dirname = servletContext.getRealPath("/deploy/");
- if (dirname == null) {
- throw new IllegalArgumentException("Web app directory not found : /deploy/");
- }
- File dir = new File(dirname);
- if (!dir.exists()) {
- throw new IllegalArgumentException("Web app directory does not exist: " + dir);
- }
- return dir;
- }
-
@Override
protected void doOnSetProperty(String key, @Nullable String value) {
deprecatedConfiguration.setProperty(key, value);
diff --git a/sonar-server/src/main/java/org/sonar/server/platform/SonarHome.java b/sonar-server/src/main/java/org/sonar/server/platform/SonarHome.java
index 26cf45ed572..2f1b7bcfafd 100644
--- a/sonar-server/src/main/java/org/sonar/server/platform/SonarHome.java
+++ b/sonar-server/src/main/java/org/sonar/server/platform/SonarHome.java
@@ -22,6 +22,7 @@ package org.sonar.server.platform;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.commons.lang.StringUtils;
+import org.sonar.api.CoreProperties;
import java.io.File;
@@ -33,6 +34,8 @@ import java.io.File;
* </ol>
*
* @since 2.12
+ *
+ * TODO Delete it as it's now useless (SONAR_HOME is set by Tomcat)
*/
final class SonarHome {
@@ -40,12 +43,10 @@ final class SonarHome {
// only static methods
}
- static final String SONAR_HOME = "SONAR_HOME";
-
static Supplier<File> homeSupplier = Suppliers.memoize(new Supplier<File>() {
public File get() {
File home = locate();
- System.setProperty(SONAR_HOME, home.getAbsolutePath());
+ System.setProperty(CoreProperties.SONAR_HOME, home.getAbsolutePath());
return home;
}
});
@@ -55,19 +56,19 @@ final class SonarHome {
}
static File locate() {
- String value = System.getProperty(SONAR_HOME);
+ String value = System.getProperty(CoreProperties.SONAR_HOME);
if (StringUtils.isBlank(value)) {
- value = System.getenv(SONAR_HOME);
+ value = System.getenv(CoreProperties.SONAR_HOME);
}
if (StringUtils.isBlank(value)) {
- throw new IllegalStateException("The system property or env variable " + SONAR_HOME + " is not set");
+ throw new IllegalStateException("The system property or env variable " + CoreProperties.SONAR_HOME + " is not set");
}
File dir = new File(value);
if (!dir.isDirectory() || !dir.exists()) {
- throw new IllegalStateException(SONAR_HOME + " is not valid: " + value + ". Please fix the env variable/system " +
- "property " + SONAR_HOME);
+ throw new IllegalStateException(CoreProperties.SONAR_HOME + " is not valid: " + value + ". Please fix the env variable/system " +
+ "property " + CoreProperties.SONAR_HOME);
}
return dir;
}
diff --git a/sonar-server/src/main/java/org/sonar/server/plugins/BatchResourcesServlet.java b/sonar-server/src/main/java/org/sonar/server/plugins/BatchResourcesServlet.java
index bcb7546ed08..f8daf5ae57e 100644
--- a/sonar-server/src/main/java/org/sonar/server/plugins/BatchResourcesServlet.java
+++ b/sonar-server/src/main/java/org/sonar/server/plugins/BatchResourcesServlet.java
@@ -23,7 +23,6 @@ import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.sonar.server.startup.GenerateBootstrapIndex;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@@ -33,7 +32,6 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.PrintWriter;
/**
* This servlet allows to load libraries from directory "WEB-INF/lib" in order to provide them for batch-bootstrapper.
@@ -48,17 +46,7 @@ public class BatchResourcesServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String filename = filename(request);
if (StringUtils.isBlank(filename)) {
- PrintWriter writer = null;
- try {
- response.setContentType("text/plain");
- writer = response.getWriter();
- writer.print(StringUtils.join(GenerateBootstrapIndex.getLibs(getServletContext()), ','));
- } catch (IOException e) {
- LOG.error("Unable to provide list of batch resources", e);
- response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- } finally {
- IOUtils.closeQuietly(writer);
- }
+ throw new IllegalArgumentException("Filename is missing.");
} else {
InputStream in = null;
OutputStream out = null;
diff --git a/sonar-server/src/main/java/org/sonar/server/source/CodeColorizers.java b/sonar-server/src/main/java/org/sonar/server/source/CodeColorizers.java
index 16509e8b9da..67803e8a6e5 100644
--- a/sonar-server/src/main/java/org/sonar/server/source/CodeColorizers.java
+++ b/sonar-server/src/main/java/org/sonar/server/source/CodeColorizers.java
@@ -19,6 +19,7 @@
*/
package org.sonar.server.source;
+import com.google.common.collect.Lists;
import org.apache.commons.lang.StringUtils;
import org.sonar.api.ServerExtension;
import org.sonar.api.utils.Logs;
@@ -49,6 +50,13 @@ public class CodeColorizers implements ServerExtension {
Logs.INFO.info("Code colorizer, supported languages: " + StringUtils.join(byLang.keySet(), ","));
}
+ /**
+ * Used when no plugin is defining some CodeColorizerFormat
+ */
+ public CodeColorizers() {
+ this(Lists.<CodeColorizerFormat>newArrayList());
+ }
+
public String toHtml(String code, String language) {
CodeColorizerFormat format = byLang.get(language);
List<Tokenizer> tokenizers;
diff --git a/sonar-server/src/main/java/org/sonar/server/startup/GenerateBootstrapIndex.java b/sonar-server/src/main/java/org/sonar/server/startup/GenerateBootstrapIndex.java
index 70def7e35b0..4b71498785a 100644
--- a/sonar-server/src/main/java/org/sonar/server/startup/GenerateBootstrapIndex.java
+++ b/sonar-server/src/main/java/org/sonar/server/startup/GenerateBootstrapIndex.java
@@ -19,22 +19,23 @@
*/
package org.sonar.server.startup;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.filefilter.FileFilterUtils;
+import org.apache.commons.io.filefilter.HiddenFileFilter;
import org.apache.commons.lang.CharUtils;
import org.apache.commons.lang.StringUtils;
+import org.sonar.api.platform.Server;
import org.sonar.home.cache.FileHashes;
import org.sonar.server.platform.DefaultServerFileSystem;
-import javax.servlet.ServletContext;
-
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
-import java.io.InputStream;
+import java.util.Collection;
import java.util.List;
-import java.util.Set;
/**
* @since 3.5
@@ -45,11 +46,13 @@ public final class GenerateBootstrapIndex {
private static final String[] IGNORE = {"jtds", "mysql", "postgresql", "jruby", "jfreechart", "eastwood",
"elasticsearch", "lucene"};
- private final ServletContext servletContext;
+ private static final String LIB_DIR = "/web/WEB-INF/lib";
+
+ private final Server server;
private final DefaultServerFileSystem fileSystem;
- public GenerateBootstrapIndex(DefaultServerFileSystem fileSystem, ServletContext servletContext) {
- this.servletContext = servletContext;
+ public GenerateBootstrapIndex(DefaultServerFileSystem fileSystem, Server server) {
+ this.server = server;
this.fileSystem = fileSystem;
}
@@ -61,25 +64,32 @@ public final class GenerateBootstrapIndex {
FileUtils.forceMkdir(indexFile.getParentFile());
FileWriter writer = new FileWriter(indexFile, false);
try {
- for (String path : getLibs(servletContext)) {
- writer.append(path);
- InputStream is = servletContext.getResourceAsStream("/WEB-INF/lib/" + path);
- writer.append("|").append(new FileHashes().of(is));
- writer.append(CharUtils.LF);
+ File libDir = new File(server.getRootDir(), LIB_DIR);
+ // TODO hack for Medium tests
+ if (libDir.exists()) {
+ for (String path : getLibs(libDir)) {
+ writer.append(path);
+ File is = new File(libDir, path);
+ writer.append("|").append(new FileHashes().of(is));
+ writer.append(CharUtils.LF);
+ }
+ writer.flush();
}
- writer.flush();
} finally {
IOUtils.closeQuietly(writer);
}
}
- public static List<String> getLibs(ServletContext servletContext) {
+ @VisibleForTesting
+ static List<String> getLibs(File libDir) {
List<String> libs = Lists.newArrayList();
- Set<String> paths = servletContext.getResourcePaths("/WEB-INF/lib/");
- for (String path : paths) {
+
+ Collection<File> files = FileUtils.listFiles(libDir, HiddenFileFilter.VISIBLE, FileFilterUtils.directoryFileFilter());
+ for (File file : files) {
+ String path = file.getPath();
if (StringUtils.endsWith(path, ".jar")) {
- String filename = StringUtils.removeStart(path, "/WEB-INF/lib/");
+ String filename = StringUtils.removeStart(path, libDir.getAbsolutePath() + "/");
if (!isIgnored(filename)) {
libs.add(filename);
}
diff --git a/sonar-server/src/main/java/org/sonar/server/startup/GwtPublisher.java b/sonar-server/src/main/java/org/sonar/server/startup/GwtPublisher.java
index 8980988255b..a69b50a758c 100644
--- a/sonar-server/src/main/java/org/sonar/server/startup/GwtPublisher.java
+++ b/sonar-server/src/main/java/org/sonar/server/startup/GwtPublisher.java
@@ -19,17 +19,18 @@
*/
package org.sonar.server.startup;
+import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.config.Settings;
+import org.sonar.api.platform.Server;
import org.sonar.api.utils.Logs;
import org.sonar.api.utils.SonarException;
import org.sonar.api.utils.TimeProfiler;
import org.sonar.api.utils.ZipUtils;
import org.sonar.api.web.GwtExtension;
-import org.sonar.server.platform.ServerSettings;
import java.io.File;
import java.io.IOException;
@@ -41,15 +42,23 @@ import java.util.zip.ZipEntry;
public class GwtPublisher {
private static final Logger LOG = LoggerFactory.getLogger(GwtPublisher.class);
- private Settings settings;
+ private Server server;
private GwtExtension[] extensions = null;
private File outputDir = null;
- public GwtPublisher(GwtExtension[] extensions, Settings settings) {
+ public GwtPublisher(GwtExtension[] extensions, Settings settings, Server server) {
this.extensions = extensions;
- this.settings = settings;
+ this.server = server;
}
+ /**
+ * Used when no plugin is defining some GwtExtension
+ */
+ public GwtPublisher(Settings settings, Server server) {
+ this(new GwtExtension[]{}, settings, server);
+ }
+
+ @VisibleForTesting
GwtPublisher(GwtExtension[] extensions, File outputDir) {
this.extensions = extensions;
this.outputDir = outputDir;
@@ -62,7 +71,7 @@ public class GwtPublisher {
TimeProfiler profiler = new TimeProfiler().start("Deploy GWT plugins");
try {
cleanDirectory();
- this.outputDir = new File(settings.getString(ServerSettings.DEPLOY_DIR), "gwt");
+ this.outputDir = new File(server.getDeployDir(), "gwt");
LoggerFactory.getLogger(GwtPublisher.class).debug("Deploy {} GWT extensions to {}", extensions.length, outputDir);
publish();
diff --git a/sonar-server/src/main/java/org/sonar/server/startup/RegisterDashboards.java b/sonar-server/src/main/java/org/sonar/server/startup/RegisterDashboards.java
index 11f85d0e53d..317e08d9a47 100644
--- a/sonar-server/src/main/java/org/sonar/server/startup/RegisterDashboards.java
+++ b/sonar-server/src/main/java/org/sonar/server/startup/RegisterDashboards.java
@@ -57,6 +57,13 @@ public class RegisterDashboards implements Startable {
this.loadedTemplateDao = loadedTemplateDao;
}
+ /**
+ * Used when no plugin is defining some DashboardTemplate
+ */
+ public RegisterDashboards(DashboardDao dashboardDao, ActiveDashboardDao activeDashboardDao, LoadedTemplateDao loadedTemplateDao) {
+ this(new DashboardTemplate[]{}, dashboardDao, activeDashboardDao, loadedTemplateDao);
+ }
+
@Override
public void start() {
TimeProfiler profiler = new TimeProfiler(LOG).start("Register dashboards");
diff --git a/sonar-server/src/main/java/org/sonar/server/startup/RegisterMetrics.java b/sonar-server/src/main/java/org/sonar/server/startup/RegisterMetrics.java
index 689348d9ca0..5e5b6cfc582 100644
--- a/sonar-server/src/main/java/org/sonar/server/startup/RegisterMetrics.java
+++ b/sonar-server/src/main/java/org/sonar/server/startup/RegisterMetrics.java
@@ -51,6 +51,13 @@ public class RegisterMetrics {
this.conditionDao = conditionDao;
}
+ /**
+ * Used when no plugin is defining Metrics
+ */
+ public RegisterMetrics(MeasuresDao measuresDao, QualityGateConditionDao conditionDao) {
+ this(measuresDao, conditionDao, new Metrics[]{});
+ }
+
public void start() {
TimeProfiler profiler = new TimeProfiler().start("Load metrics");
measuresDao.disableAutomaticMetrics();
diff --git a/sonar-server/src/main/java/org/sonar/server/startup/RegisterNewMeasureFilters.java b/sonar-server/src/main/java/org/sonar/server/startup/RegisterNewMeasureFilters.java
index e2c8574b838..755a1eed6a6 100644
--- a/sonar-server/src/main/java/org/sonar/server/startup/RegisterNewMeasureFilters.java
+++ b/sonar-server/src/main/java/org/sonar/server/startup/RegisterNewMeasureFilters.java
@@ -54,6 +54,13 @@ public final class RegisterNewMeasureFilters {
this.loadedTemplateDao = loadedTemplateDao;
}
+ /**
+ * Used when no plugin is defining some FilterTemplate
+ */
+ public RegisterNewMeasureFilters(MeasureFilterDao filterDao, LoadedTemplateDao loadedTemplateDao) {
+ this(new FilterTemplate[]{}, filterDao, loadedTemplateDao);
+ }
+
public void start() {
TimeProfiler profiler = new TimeProfiler(LOG).start("Register measure filters");
diff --git a/sonar-server/src/main/java/org/sonar/server/text/MacroInterpreter.java b/sonar-server/src/main/java/org/sonar/server/text/MacroInterpreter.java
index 0f8c60ac335..0971feae8a0 100644
--- a/sonar-server/src/main/java/org/sonar/server/text/MacroInterpreter.java
+++ b/sonar-server/src/main/java/org/sonar/server/text/MacroInterpreter.java
@@ -22,17 +22,17 @@ package org.sonar.server.text;
import com.google.common.collect.ImmutableList;
import org.sonar.api.ServerComponent;
+import org.sonar.api.platform.Server;
-import javax.servlet.ServletContext;
import java.util.List;
public class MacroInterpreter implements ServerComponent {
private final List<Macro> macros;
- public MacroInterpreter(ServletContext servletContext) {
+ public MacroInterpreter(Server server) {
this.macros = ImmutableList.<Macro>of(
- new RuleMacro(servletContext.getContextPath())
+ new RuleMacro(server.getContextPath())
);
}
diff --git a/sonar-server/src/test/java/org/sonar/server/platform/PersistentSettingsTest.java b/sonar-server/src/test/java/org/sonar/server/platform/PersistentSettingsTest.java
index cc6f008d474..3612c104526 100644
--- a/sonar-server/src/test/java/org/sonar/server/platform/PersistentSettingsTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/platform/PersistentSettingsTest.java
@@ -28,9 +28,9 @@ import org.sonar.api.config.PropertyDefinitions;
import org.sonar.core.properties.PropertiesDao;
import org.sonar.core.properties.PropertyDto;
-import java.io.File;
import java.net.URISyntaxException;
import java.util.Arrays;
+import java.util.Properties;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.argThat;
@@ -44,11 +44,11 @@ public class PersistentSettingsTest {
@Before
public void init() throws URISyntaxException {
dao = mock(PropertiesDao.class);
+
settings = new ServerSettings(
new PropertyDefinitions(),
new PropertiesConfiguration(),
- new File("."),
- new File(PersistentSettingsTest.class.getResource("/org/sonar/server/platform/PersistentSettingsTest/").toURI()));
+ new Properties());
}
@Test
diff --git a/sonar-server/src/test/java/org/sonar/server/platform/ServerImplTest.java b/sonar-server/src/test/java/org/sonar/server/platform/ServerImplTest.java
index 2101db16a78..44954c85fb6 100644
--- a/sonar-server/src/test/java/org/sonar/server/platform/ServerImplTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/platform/ServerImplTest.java
@@ -20,22 +20,41 @@
package org.sonar.server.platform;
import org.hamcrest.core.Is;
+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.api.CoreProperties;
import org.sonar.api.config.Settings;
+import java.io.File;
+
import static org.fest.assertions.Assertions.assertThat;
import static org.junit.Assert.assertThat;
public class ServerImplTest {
+
@Rule
public ExpectedException exception = ExpectedException.none();
+ @Rule
+ public TemporaryFolder sonarHome = new TemporaryFolder();
+
+ Settings settings;
+
+ ServerImpl server;
+
+ @Before
+ public void setUp() throws Exception {
+ settings = new Settings().setProperty(CoreProperties.SONAR_HOME, sonarHome.getRoot().getAbsolutePath());
+ new File(sonarHome.getRoot(), "web/deploy").mkdirs();
+
+ server = new ServerImpl(settings, "/org/sonar/server/platform/ServerImplTest/build.properties", "/org/sonar/server/platform/ServerImplTest/version.txt");
+ }
+
@Test
- public void alwaysReturnTheSameValues() {
- ServerImpl server = new ServerImpl(new Settings(), "", "/org/sonar/server/platform/ServerImplTest/pom-with-version.properties");
+ public void always_return_the_same_values() {
server.start();
assertThat(server.getId()).isNotNull();
@@ -49,52 +68,48 @@ public class ServerImplTest {
}
@Test
- public void getVersionFromFile() {
- ServerImpl server = new ServerImpl(new Settings(), "", "/org/sonar/server/platform/ServerImplTest/pom-with-version.properties");
+ public void read_version_from_file() {
server.start();
assertThat(server.getVersion()).isEqualTo("1.0");
}
@Test
- public void getImplementationBuildFromManifest() {
- ServerImpl server = new ServerImpl(new Settings(),
- "/org/sonar/server/platform/ServerImplTest/build.properties",
- "/org/sonar/server/platform/ServerImplTest/pom-with-version.properties");
+ public void read_implementation_build_from_manifest() {
server.start();
assertThat(server.getImplementationBuild()).isEqualTo("0b9545a8b74aca473cb776275be4dc93a327c363");
}
@Test
- public void testFileWithNoVersion() {
+ public void read_file_with_no_version() {
exception.expect(IllegalStateException.class);
exception.expectMessage("Unknown SonarQube version");
- ServerImpl server = new ServerImpl(new Settings(), "", "/org/sonar/server/platform/ServerImplTest/pom-without-version.properties");
+ ServerImpl server = new ServerImpl(settings, "", "/org/sonar/server/platform/ServerImplTest/empty-version.txt");
server.start();
}
@Test
- public void testFileWithEmptyVersionParameter() {
+ public void read_file_with_empty_version() {
exception.expect(IllegalStateException.class);
exception.expectMessage("Unknown SonarQube version");
- ServerImpl server = new ServerImpl(new Settings(), "", "/org/sonar/server/platform/ServerImplTest/pom-with-empty-version.properties");
+ ServerImpl server = new ServerImpl(settings, "", "/org/sonar/server/platform/ServerImplTest/empty-version.txt");
server.start();
}
@Test
- public void shouldFailIfFileNotFound() {
+ public void fail_if_version_file_not_found() {
exception.expect(IllegalStateException.class);
exception.expectMessage("Unknown SonarQube version");
- ServerImpl server = new ServerImpl(new Settings(), "", "/org/sonar/server/platform/ServerImplTest/unknown-file.properties");
+ ServerImpl server = new ServerImpl(settings, "", "/org/sonar/server/platform/ServerImplTest/unknown-file.properties");
server.start();
}
@Test
- public void shouldLoadServerIdFromDatabase() {
+ public void load_server_id_from_database() {
Settings settings = new Settings();
settings.setProperty(CoreProperties.PERMANENT_SERVER_ID, "abcde");
@@ -102,4 +117,18 @@ public class ServerImplTest {
assertThat(server.getPermanentServerId(), Is.is("abcde"));
}
+
+ @Test
+ public void use_default_context_path() {
+ server.start();
+ assertThat(server.getContextPath()).isEqualTo("/");
+ }
+
+ @Test
+ public void get_context_path_from_settings() {
+ settings.setProperty("sonar.web.context", "/my_path");
+ server.start();
+ assertThat(server.getContextPath()).isEqualTo("/my_path");
+ }
+
}
diff --git a/sonar-server/src/test/java/org/sonar/server/platform/ServerLifecycleNotifierTest.java b/sonar-server/src/test/java/org/sonar/server/platform/ServerLifecycleNotifierTest.java
index 4acb5baf2ce..8907b3e6d5d 100644
--- a/sonar-server/src/test/java/org/sonar/server/platform/ServerLifecycleNotifierTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/platform/ServerLifecycleNotifierTest.java
@@ -21,10 +21,11 @@ package org.sonar.server.platform;
import org.junit.Before;
import org.junit.Test;
+import org.sonar.api.platform.Server;
import org.sonar.api.platform.ServerStartHandler;
import org.sonar.api.platform.ServerStopHandler;
-import org.sonar.api.platform.Server;
+import java.io.File;
import java.util.Date;
import static org.mockito.Mockito.*;
@@ -100,6 +101,21 @@ class FakeServer extends Server {
}
@Override
+ public File getRootDir() {
+ return null;
+ }
+
+ @Override
+ public File getDeployDir() {
+ return null;
+ }
+
+ @Override
+ public String getContextPath() {
+ return null;
+ }
+
+ @Override
public String getURL() {
return null;
}
diff --git a/sonar-server/src/test/java/org/sonar/server/platform/ServerSettingsTest.java b/sonar-server/src/test/java/org/sonar/server/platform/ServerSettingsTest.java
index 4b7ef9b0edf..af0cc558e8f 100644
--- a/sonar-server/src/test/java/org/sonar/server/platform/ServerSettingsTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/platform/ServerSettingsTest.java
@@ -21,44 +21,37 @@ package org.sonar.server.platform;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.configuration.BaseConfiguration;
+import org.junit.Before;
import org.junit.Test;
import org.sonar.api.config.PropertyDefinitions;
-import java.io.File;
-import java.net.URISyntaxException;
import java.util.Map;
+import java.util.Properties;
import static org.fest.assertions.Assertions.assertThat;
public class ServerSettingsTest {
- private static File home = getHome();
+ Properties properties;
- @Test
- public void load_properties_file() {
- ServerSettings settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), home);
+ ServerSettings settings;
- assertThat(settings.getString("hello")).isEqualTo("world");
+ @Before
+ public void before() throws Exception {
+ properties = new Properties();
+ properties.put("hello", "world");
+ properties.put("in_file", "true");
+ properties.put("ServerSettingsTestEnv", "in_file");
+ settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), properties);
}
@Test
- public void systemPropertiesShouldOverridePropertiesFile() {
- System.setProperty("ServerSettingsTestEnv", "in_env");
- ServerSettings settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), home);
-
- assertThat(settings.getString("ServerSettingsTestEnv")).isEqualTo("in_env");
- }
-
- @Test(expected = IllegalStateException.class)
- public void fail_if_properties_file_is_not_found() {
- File sonarHome = new File("unknown/path");
- new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), sonarHome);
+ public void load_properties_file() {
+ assertThat(settings.getString("hello")).isEqualTo("world");
}
@Test
- public void activateDatabaseSettings() {
- ServerSettings settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), home);
-
+ public void activate_database_settings() {
Map<String, String> databaseProperties = ImmutableMap.of("in_db", "true");
settings.activateDatabaseSettings(databaseProperties);
@@ -67,7 +60,6 @@ public class ServerSettingsTest {
@Test
public void file_settings_override_db_settings() {
- ServerSettings settings = new ServerSettings(new PropertyDefinitions(), new BaseConfiguration(), new File("."), home);
assertThat(settings.getString("in_file")).isEqualTo("true");
Map<String, String> databaseProperties = ImmutableMap.of("in_file", "false");
@@ -79,7 +71,7 @@ public class ServerSettingsTest {
@Test
public void synchronize_deprecated_commons_configuration() {
BaseConfiguration deprecated = new BaseConfiguration();
- ServerSettings settings = new ServerSettings(new PropertyDefinitions(), deprecated, new File("."), home);
+ ServerSettings settings = new ServerSettings(new PropertyDefinitions(), deprecated, properties);
assertThat(settings.getString("in_file")).isEqualTo("true");
assertThat(deprecated.getString("in_file")).isEqualTo("true");
@@ -90,12 +82,4 @@ public class ServerSettingsTest {
settings.removeProperty("foo");
assertThat(deprecated.getString("foo")).isNull();
}
-
- private static File getHome() {
- try {
- return new File(ServerSettingsTest.class.getResource("/org/sonar/server/platform/ServerSettingsTest/").toURI());
- } catch (URISyntaxException e) {
- throw new IllegalStateException(e);
- }
- }
}
diff --git a/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginJarsInstallerTest.java b/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginJarsInstallerTest.java
index caf2b8f7acc..fc0ef01ada4 100644
--- a/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginJarsInstallerTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/plugins/ServerPluginJarsInstallerTest.java
@@ -50,7 +50,7 @@ public class ServerPluginJarsInstallerTest {
public TemporaryFolder temp = new TemporaryFolder();
DefaultServerFileSystem fileSystem;
- File homeDir, deployDir, pluginsDir, downloadsDir, bundledDir, trashDir, coreDir;
+ File homeDir, pluginsDir, downloadsDir, bundledDir, trashDir, coreDir;
ServerPluginJarInstaller jarInstaller;
ServerPluginJarsInstaller jarsInstaller;
Server server = mock(Server.class);
@@ -67,8 +67,7 @@ public class ServerPluginJarsInstallerTest {
bundledDir = new File(homeDir, "lib/bundled-plugins");
coreDir = new File(homeDir, "lib/core-plugins");
FileUtils.forceMkdir(bundledDir);
- deployDir = temp.newFolder("deploy");
- fileSystem = new DefaultServerFileSystem(mock(Database.class), homeDir, deployDir);
+ fileSystem = new DefaultServerFileSystem(mock(Database.class), homeDir, server);
jarInstaller = new ServerPluginJarInstaller();
jarsInstaller = new ServerPluginJarsInstaller(server, upgradeStatus, fileSystem, jarInstaller);
}
diff --git a/sonar-server/src/test/java/org/sonar/server/startup/GenerateBootstrapIndexTest.java b/sonar-server/src/test/java/org/sonar/server/startup/GenerateBootstrapIndexTest.java
index 3b4686a461c..ca6f7c74e0e 100644
--- a/sonar-server/src/test/java/org/sonar/server/startup/GenerateBootstrapIndexTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/startup/GenerateBootstrapIndexTest.java
@@ -19,40 +19,41 @@
*/
package org.sonar.server.startup;
-import com.google.common.collect.Sets;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
-import javax.servlet.ServletContext;
-
-import java.util.Set;
+import java.io.File;
+import java.io.IOException;
import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
public class GenerateBootstrapIndexTest {
+ @Rule
+ public TemporaryFolder rootDir = new TemporaryFolder();
+
@Before
public void setUp() throws Exception {
}
@Test
- public void shouldDetermineListOfResources() {
- ServletContext servletContext = mock(ServletContext.class);
- Set<String> libs = Sets.newHashSet();
- libs.add("/WEB-INF/lib/sonar-core-2.6.jar");
- libs.add("/WEB-INF/lib/treemap.rb");
- libs.add("/WEB-INF/lib/directory/");
- when(servletContext.getResourcePaths(anyString())).thenReturn(libs);
+ public void determine_list_of_resources() throws IOException {
+ new File(rootDir.getRoot(), "/web/WEB-INF/lib").mkdirs();
+ File webInf = new File(rootDir.getRoot(), "/web/WEB-INF");
+ File lib = new File(rootDir.getRoot(), "/web/WEB-INF/lib");
+ new File(webInf, "directory").mkdir();
+ new File(lib, "sonar-core-2.6.jar").createNewFile();
+ new File(lib, "treemap.rbr").createNewFile();
+ new File(lib, "sonar-core-2.6.jar").createNewFile();
- assertThat(GenerateBootstrapIndex.getLibs(servletContext)).hasSize(1);
- assertThat(GenerateBootstrapIndex.getLibs(servletContext).get(0)).isEqualTo("sonar-core-2.6.jar");
+ assertThat(GenerateBootstrapIndex.getLibs(lib)).hasSize(1);
+ assertThat(GenerateBootstrapIndex.getLibs(lib).get(0)).isEqualTo("sonar-core-2.6.jar");
}
@Test
- public void shouldIgnore() {
+ public void ignore_some_jars() {
assertThat(GenerateBootstrapIndex.isIgnored("sonar-batch-2.6-SNAPSHOT.jar")).isFalse();
assertThat(GenerateBootstrapIndex.isIgnored("mysql-connector-java-5.1.13.jar")).isTrue();
assertThat(GenerateBootstrapIndex.isIgnored("postgresql-9.0-801.jdbc3.jar")).isTrue();
diff --git a/sonar-server/src/test/java/org/sonar/server/startup/GwtPublisherTest.java b/sonar-server/src/test/java/org/sonar/server/startup/GwtPublisherTest.java
index fc6ffdc3945..8e900809fc4 100644
--- a/sonar-server/src/test/java/org/sonar/server/startup/GwtPublisherTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/startup/GwtPublisherTest.java
@@ -45,7 +45,6 @@ public class GwtPublisherTest {
outputDir = new File("./target/test-tmp/org/sonar/server/startup/GwtPublisherTest/output");
if (outputDir.exists()) {
FileUtils.forceDelete(outputDir);
-
}
}
diff --git a/sonar-server/src/test/java/org/sonar/server/text/MacroInterpreterTest.java b/sonar-server/src/test/java/org/sonar/server/text/MacroInterpreterTest.java
index ef9ad6775ae..b993dbfd058 100644
--- a/sonar-server/src/test/java/org/sonar/server/text/MacroInterpreterTest.java
+++ b/sonar-server/src/test/java/org/sonar/server/text/MacroInterpreterTest.java
@@ -22,8 +22,7 @@ package org.sonar.server.text;
import org.junit.Before;
import org.junit.Test;
-
-import javax.servlet.ServletContext;
+import org.sonar.api.platform.Server;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@@ -36,9 +35,9 @@ public class MacroInterpreterTest {
@Before
public void setUp() {
- ServletContext servletContext = mock(ServletContext.class);
- when(servletContext.getContextPath()).thenReturn(path);
- interpreter = new MacroInterpreter(servletContext);
+ Server server = mock(Server.class);
+ when(server.getContextPath()).thenReturn(path);
+ interpreter = new MacroInterpreter(server);
}
@Test
diff --git a/sonar-server/src/test/resources/org/sonar/server/platform/PersistentSettingsTest/conf/sonar.properties b/sonar-server/src/test/resources/org/sonar/server/platform/PersistentSettingsTest/conf/sonar.properties
deleted file mode 100644
index b4a8077471c..00000000000
--- a/sonar-server/src/test/resources/org/sonar/server/platform/PersistentSettingsTest/conf/sonar.properties
+++ /dev/null
@@ -1 +0,0 @@
-in_file: true \ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/empty-version.txt b/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/empty-version.txt
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/empty-version.txt
diff --git a/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-with-empty-version.properties b/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-with-empty-version.properties
deleted file mode 100644
index 287ce487033..00000000000
--- a/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-with-empty-version.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-#Generated by Maven
-#Fri Nov 23 14:23:53 CET 2007
-groupId=org.codehaus.sonar
-artifactId=sonar-core
-version= \ No newline at end of file
diff --git a/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-with-version.properties b/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-with-version.properties
deleted file mode 100644
index 6fff0c5f4d1..00000000000
--- a/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-with-version.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-#Generated by Maven
-#Fri Nov 23 14:23:53 CET 2007
-version=1.0
-groupId=org.codehaus.sonar
-artifactId=sonar-core
diff --git a/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-without-version.properties b/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-without-version.properties
deleted file mode 100644
index 8d70c2289f8..00000000000
--- a/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/pom-without-version.properties
+++ /dev/null
@@ -1,4 +0,0 @@
-#Generated by Maven
-#Fri Nov 23 14:23:53 CET 2007
-groupId=org.codehaus.sonar
-artifactId=sonar-core
diff --git a/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/version.txt b/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/version.txt
new file mode 100644
index 00000000000..d3827e75a5c
--- /dev/null
+++ b/sonar-server/src/test/resources/org/sonar/server/platform/ServerImplTest/version.txt
@@ -0,0 +1 @@
+1.0
diff --git a/sonar-server/src/test/resources/org/sonar/server/platform/ServerSettingsTest/conf/sonar.properties b/sonar-server/src/test/resources/org/sonar/server/platform/ServerSettingsTest/conf/sonar.properties
deleted file mode 100644
index 020777dad4f..00000000000
--- a/sonar-server/src/test/resources/org/sonar/server/platform/ServerSettingsTest/conf/sonar.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-hello: world
-in_file: true
-ServerSettingsTestEnv: in_file \ No newline at end of file