summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>2016-03-16 13:42:31 +0100
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>2016-03-21 16:44:05 +0100
commit37e32de9c0fb62c14bff9f750332324d542c9cee (patch)
treec0798dc7fd73405849f74f6dd196294bc7598eda
parenta9a7a8a7a6b0b0aa1b59db3206c668cbf129da7e (diff)
downloadsonarqube-37e32de9c0fb62c14bff9f750332324d542c9cee.tar.gz
sonarqube-37e32de9c0fb62c14bff9f750332324d542c9cee.zip
SONAR-6732 CE must load Settings from DB for each worker
renamed ServerSettings to WebServerSettings and extract from it a ServerSetting interface to be able to easily provide separte implementations for Web Server and CE) CE Server implementation is called ComputeEngineSettings which supports loading up to date Settings for a specific worker using delegation and a ThreadLocal
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java6
-rw-r--r--server/sonar-server/src/main/java/org/sonar/ce/settings/ComputeEngineSettings.java333
-rw-r--r--server/sonar-server/src/main/java/org/sonar/ce/settings/ThreadLocalSettings.java34
-rw-r--r--server/sonar-server/src/main/java/org/sonar/ce/settings/package-info.java23
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java7
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/report/ReportTaskProcessor.java14
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/PersistentSettings.java22
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerSettings.java70
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/WebServerSettings.java72
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/PersistentSettingsTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/platform/ServerSettingsTest.java4
-rw-r--r--sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java7
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java6
16 files changed, 546 insertions, 65 deletions
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
index 3d16c5fbeb7..2ba3b853a77 100644
--- a/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/ComputeEngineContainerImpl.java
@@ -37,6 +37,7 @@ import org.sonar.api.utils.System2;
import org.sonar.api.utils.UriReader;
import org.sonar.ce.es.EsIndexerEnabler;
import org.sonar.ce.property.CePropertyDefinitions;
+import org.sonar.ce.settings.ComputeEngineSettings;
import org.sonar.core.component.DefaultResourceTypes;
import org.sonar.core.config.CorePropertyDefinitions;
import org.sonar.core.i18n.DefaultI18n;
@@ -106,7 +107,6 @@ import org.sonar.server.platform.ServerIdGenerator;
import org.sonar.server.platform.ServerImpl;
import org.sonar.server.platform.ServerLifecycleNotifier;
import org.sonar.server.platform.ServerLogging;
-import org.sonar.server.platform.ServerSettings;
import org.sonar.server.platform.TempFolderProvider;
import org.sonar.server.plugins.InstalledPluginReferentialFactory;
import org.sonar.server.plugins.ServerExtensionInstaller;
@@ -139,8 +139,8 @@ import org.sonarqube.ws.Rules;
public class ComputeEngineContainerImpl implements ComputeEngineContainer {
private static final Object[] LEVEL_1_COMPONENTS = new Object[] {
+ ComputeEngineSettings.class,
new SonarQubeVersionProvider(),
- ServerSettings.class,
ServerImpl.class,
UuidFactoryImpl.INSTANCE,
// no EmbeddedDatabaseFactory.class, creating H2 DB if responsibility of WebServer
@@ -160,7 +160,7 @@ public class ComputeEngineContainerImpl implements ComputeEngineContainer {
// DB
DbClient.class,
DaoModule.class,
- // MigrationStepModule.class, DB maintenance, responsibility of Web Server
+ // MigrationStepModule.class, DB maintenance, responsibility of Web Server
// Elasticsearch
EsSearchModule.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/ce/settings/ComputeEngineSettings.java b/server/sonar-server/src/main/java/org/sonar/ce/settings/ComputeEngineSettings.java
new file mode 100644
index 00000000000..a11eeef1829
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/ce/settings/ComputeEngineSettings.java
@@ -0,0 +1,333 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.ce.settings;
+
+import com.google.common.base.Objects;
+import com.google.common.collect.Maps;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.Encryption;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+import org.sonar.core.platform.ComponentContainer;
+import org.sonar.db.DbClient;
+import org.sonar.db.property.PropertyDto;
+import org.sonar.server.platform.ServerSettings;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * This class implements ServerSettings and extends Settings so that it can be injected in any component depending upon
+ * either ServerSettings or Settings.
+ *
+ * <p>
+ * In order to honor both Settings and ThreadLocalSettings contracts, none of the code inherited from the Settings super
+ * class is actually used. Every public method of Settings is override and their implementation is delegated to
+ * an inner object which can either be the default one or one specific to the current Thread. Selected of the inner
+ * object will depend on whether the current Thread made use of method {@link #load()} or not. This approach also greatly
+ * simplifies delegation code (see {@link #currentDelegate()}).
+ * </p>
+ */
+public class ComputeEngineSettings extends Settings implements ThreadLocalSettings, ServerSettings {
+ private final ServerSettings defaultDelegate;
+ private final ThreadLocal<ServerSettings> threadLocalDelegate = new ThreadLocal<>();
+
+ private final Properties rootProperties;
+ private final ComponentContainer componentContainer;
+ // we can't get injected with DBClient because it creates a circular dependency
+ private volatile DbClient dbClient;
+
+ public ComputeEngineSettings(PropertyDefinitions definitions, Properties rootProperties, ComponentContainer componentContainer) {
+ super(definitions);
+ this.rootProperties = rootProperties;
+ this.componentContainer = componentContainer;
+
+ this.defaultDelegate = new ServerSettingsImpl(definitions, rootProperties);
+ }
+
+ @Override
+ public void load() {
+ checkState(
+ this.threadLocalDelegate.get() == null,
+ "loadLocal called twice for Thread '%' or state wasn't cleared last time it was used",
+ Thread.currentThread().getName());
+ this.threadLocalDelegate.set(loadServerSettings());
+ }
+
+ @Override
+ public void remove() {
+ this.threadLocalDelegate.remove();
+ }
+
+ private ServerSettings loadServerSettings() {
+ ServerSettings res = new ServerSettingsImpl(this.definitions, this.rootProperties);
+ Map<String, String> databaseProperties = Maps.newHashMap();
+ for (PropertyDto property : getDbClient().propertiesDao().selectGlobalProperties()) {
+ databaseProperties.put(property.getKey(), property.getValue());
+ }
+ res.activateDatabaseSettings(databaseProperties);
+ return res;
+ }
+
+ private DbClient getDbClient() {
+ if (dbClient == null) {
+ this.dbClient = componentContainer.getComponentByType(DbClient.class);
+ }
+ return dbClient;
+ }
+
+ private ServerSettings currentDelegate() {
+ return Objects.firstNonNull(threadLocalDelegate.get(), defaultDelegate);
+ }
+
+ private Settings currentSettings() {
+ return currentDelegate().getSettings();
+ }
+
+ @Override
+ public ServerSettings activateDatabaseSettings(Map<String, String> databaseProperties) {
+ checkState(threadLocalDelegate.get() == null, "activateDatabaseSettings must not be called from a Worker");
+
+ return defaultDelegate.activateDatabaseSettings(databaseProperties);
+ }
+
+ private static final class ServerSettingsImpl extends Settings implements ServerSettings {
+
+ private final Properties rootProperties;
+
+ public ServerSettingsImpl(PropertyDefinitions definitions, Properties rootProperties) {
+ super(definitions);
+ this.rootProperties = rootProperties;
+ addProperties(rootProperties);
+ // Secret key is loaded from conf/sonar.properties
+ getEncryption().setPathToSecretKey(getString(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
+ }
+
+ @Override
+ public ServerSettings activateDatabaseSettings(Map<String, String> databaseProperties) {
+ clear();
+
+ // order is important : the last override the first
+ addProperties(databaseProperties);
+ addProperties(rootProperties);
+
+ return this;
+ }
+
+ @Override
+ public Settings getSettings() {
+ return this;
+ }
+ }
+
+ @Override
+ public Settings getSettings() {
+ return this;
+ }
+
+ @Override
+ public Encryption getEncryption() {
+ return currentSettings().getEncryption();
+ }
+
+ @Override
+ @CheckForNull
+ public String getDefaultValue(String key) {
+ return currentSettings().getDefaultValue(key);
+ }
+
+ @Override
+ public boolean hasKey(String key) {
+ return currentSettings().hasKey(key);
+ }
+
+ @Override
+ public boolean hasDefaultValue(String key) {
+ return currentSettings().hasDefaultValue(key);
+ }
+
+ @Override
+ @CheckForNull
+ public String getString(String key) {
+ return currentDelegate().getString(key);
+ }
+
+ @Override
+ public boolean getBoolean(String key) {
+ return currentSettings().getBoolean(key);
+ }
+
+ @Override
+ public int getInt(String key) {
+ return currentSettings().getInt(key);
+ }
+
+ @Override
+ public long getLong(String key) {
+ return currentSettings().getLong(key);
+ }
+
+ @Override
+ @CheckForNull
+ public Date getDate(String key) {
+ return currentSettings().getDate(key);
+ }
+
+ @Override
+ @CheckForNull
+ public Date getDateTime(String key) {
+ return currentSettings().getDateTime(key);
+ }
+
+ @Override
+ @CheckForNull
+ public Float getFloat(String key) {
+ return currentSettings().getFloat(key);
+ }
+
+ @Override
+ @CheckForNull
+ public Double getDouble(String key) {
+ return currentSettings().getDouble(key);
+ }
+
+ @Override
+ public String[] getStringArray(String key) {
+ return currentSettings().getStringArray(key);
+ }
+
+ @Override
+ public String[] getStringLines(String key) {
+ return currentSettings().getStringLines(key);
+ }
+
+ @Override
+ public String[] getStringArrayBySeparator(String key, String separator) {
+ return currentSettings().getStringArrayBySeparator(key, separator);
+ }
+
+ @Override
+ public List<String> getKeysStartingWith(String prefix) {
+ return currentSettings().getKeysStartingWith(prefix);
+ }
+
+ @Override
+ public Settings appendProperty(String key, String value) {
+ return currentSettings().appendProperty(key, value);
+ }
+
+ @Override
+ public Settings setProperty(String key, @Nullable String[] values) {
+ return currentSettings().setProperty(key, values);
+ }
+
+ @Override
+ public Settings setProperty(String key, @Nullable String value) {
+ return currentSettings().setProperty(key, value);
+ }
+
+ @Override
+ public Settings setProperty(String key, @Nullable Boolean value) {
+ return currentSettings().setProperty(key, value);
+ }
+
+ @Override
+ public Settings setProperty(String key, @Nullable Integer value) {
+ return currentSettings().setProperty(key, value);
+ }
+
+ @Override
+ public Settings setProperty(String key, @Nullable Long value) {
+ return currentSettings().setProperty(key, value);
+ }
+
+ @Override
+ public Settings setProperty(String key, @Nullable Double value) {
+ return currentSettings().setProperty(key, value);
+ }
+
+ @Override
+ public Settings setProperty(String key, @Nullable Float value) {
+ return currentSettings().setProperty(key, value);
+ }
+
+ @Override
+ public Settings setProperty(String key, @Nullable Date date) {
+ return currentSettings().setProperty(key, date);
+ }
+
+ @Override
+ public Settings addProperties(Map<String, String> props) {
+ return currentSettings().addProperties(props);
+ }
+
+ @Override
+ public Settings addProperties(Properties props) {
+ return currentSettings().addProperties(props);
+ }
+
+ @Override
+ @Deprecated
+ public Settings addSystemProperties() {
+ return currentSettings().addSystemProperties();
+ }
+
+ @Override
+ @Deprecated
+ public Settings addEnvironmentVariables() {
+ return currentSettings().addEnvironmentVariables();
+ }
+
+ @Override
+ public Settings setProperties(Map<String, String> props) {
+ return currentSettings().setProperties(props);
+ }
+
+ @Override
+ public Settings setProperty(String key, @Nullable Date date, boolean includeTime) {
+ return currentSettings().setProperty(key, date, includeTime);
+ }
+
+ @Override
+ public Settings removeProperty(String key) {
+ return currentSettings().removeProperty(key);
+ }
+
+ @Override
+ public Settings clear() {
+ return currentSettings().clear();
+ }
+
+ @Override
+ public Map<String, String> getProperties() {
+ return currentSettings().getProperties();
+ }
+
+ @Override
+ public PropertyDefinitions getDefinitions() {
+ return currentSettings().getDefinitions();
+ }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/ce/settings/ThreadLocalSettings.java b/server/sonar-server/src/main/java/org/sonar/ce/settings/ThreadLocalSettings.java
new file mode 100644
index 00000000000..a525606b16d
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/ce/settings/ThreadLocalSettings.java
@@ -0,0 +1,34 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.ce.settings;
+
+public interface ThreadLocalSettings {
+ /**
+ * Loads up-to-date Settings specific to the current thread.
+ *
+ * @throws IllegalStateException if the current thread already has specific Settings
+ */
+ void load();
+
+ /**
+ * Clears the Settings specific to the current thread (if any).
+ */
+ void remove();
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/ce/settings/package-info.java b/server/sonar-server/src/main/java/org/sonar/ce/settings/package-info.java
new file mode 100644
index 00000000000..a8e314bea56
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/ce/settings/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.ce.settings;
+
+import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java
index b4fdae4b08a..f0e6d0e62bd 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ComputeEngineContainerImpl.java
@@ -31,6 +31,7 @@ import org.picocontainer.behaviors.OptInCaching;
import org.picocontainer.lifecycle.ReflectionLifecycleStrategy;
import org.picocontainer.monitors.ComponentMonitorHelper;
import org.picocontainer.monitors.NullComponentMonitor;
+import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.core.platform.ComponentContainer;
@@ -47,7 +48,7 @@ public class ComputeEngineContainerImpl extends ComponentContainer implements Co
private static final Logger LOG = Loggers.get(ComputeEngineContainerImpl.class);
public ComputeEngineContainerImpl(ComponentContainer parent, ContainerPopulator<ComputeEngineContainer> populator) {
- super(createContainer(requireNonNull(parent)));
+ super(createContainer(requireNonNull(parent)), parent.getComponentByType(PropertyDefinitions.class));
populateContainer(requireNonNull(populator));
startComponents();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java
index 82ed25a8009..1c79df7d1cb 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/container/ReportComputeEngineContainerPopulator.java
@@ -22,6 +22,7 @@ package org.sonar.server.computation.container;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nullable;
+import org.sonar.ce.queue.CeTask;
import org.sonar.core.issue.tracking.Tracker;
import org.sonar.core.platform.ContainerPopulator;
import org.sonar.server.computation.analysis.AnalysisMetadataHolderImpl;
@@ -81,7 +82,6 @@ import org.sonar.server.computation.qualitymodel.NewQualityModelMeasuresVisitor;
import org.sonar.server.computation.qualitymodel.QualityModelMeasuresVisitor;
import org.sonar.server.computation.qualitymodel.RatingSettings;
import org.sonar.server.computation.qualityprofile.ActiveRulesHolderImpl;
-import org.sonar.ce.queue.CeTask;
import org.sonar.server.computation.scm.ScmInfoRepositoryImpl;
import org.sonar.server.computation.source.LastCommitVisitor;
import org.sonar.server.computation.source.SourceHashRepositoryImpl;
@@ -121,6 +121,8 @@ public final class ReportComputeEngineContainerPopulator implements ContainerPop
private static List componentClasses() {
return Arrays.asList(
ComputationStepExecutor.class,
+
+ // File System
new ComputationTempFolderProvider(),
MetricModule.class,
@@ -172,7 +174,8 @@ public final class ReportComputeEngineContainerPopulator implements ContainerPop
TestErrorRule.class,
SkippedTestRule.class,
- // order is important: RuleTypeCopier must be the first one. And DebtAggregator must be before NewDebtAggregator (new debt requires debt)
+ // order is important: RuleTypeCopier must be the first one. And DebtAggregator must be before NewDebtAggregator (new debt requires
+ // debt)
RuleTypeCopier.class,
RuleTagsCopier.class,
DebtCalculator.class,
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/report/ReportTaskProcessor.java b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/report/ReportTaskProcessor.java
index 22c5f350121..912177763db 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/report/ReportTaskProcessor.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/taskprocessor/report/ReportTaskProcessor.java
@@ -22,14 +22,15 @@ package org.sonar.server.computation.taskprocessor.report;
import java.util.Collections;
import java.util.Set;
import javax.annotation.CheckForNull;
+import org.sonar.ce.queue.CeTask;
+import org.sonar.ce.queue.CeTaskResult;
+import org.sonar.ce.settings.ThreadLocalSettings;
+import org.sonar.ce.taskprocessor.CeTaskProcessor;
import org.sonar.core.platform.ComponentContainer;
import org.sonar.db.ce.CeTaskTypes;
import org.sonar.server.computation.container.ComputeEngineContainer;
import org.sonar.server.computation.container.ContainerFactory;
-import org.sonar.ce.queue.CeTask;
-import org.sonar.ce.queue.CeTaskResult;
import org.sonar.server.computation.step.ComputationStepExecutor;
-import org.sonar.ce.taskprocessor.CeTaskProcessor;
import org.sonar.server.computation.taskprocessor.TaskResultHolder;
import org.sonar.server.devcockpit.DevCockpitBridge;
@@ -68,10 +69,17 @@ public class ReportTaskProcessor implements CeTaskProcessor {
@Override
public CeTaskResult process(CeTask task) {
ComputeEngineContainer ceContainer = containerFactory.create(serverContainer, task, devCockpitBridge);
+ ThreadLocalSettings ceSettings = null;
try {
+ ceSettings = ceContainer.getComponentByType(ThreadLocalSettings.class);
+ ceSettings.load();
+
ceContainer.getComponentByType(ComputationStepExecutor.class).execute();
return ceContainer.getComponentByType(TaskResultHolder.class).getResult();
} finally {
+ if (ceSettings != null) {
+ ceSettings.remove();
+ }
ceContainer.cleanup();
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/PersistentSettings.java b/server/sonar-server/src/main/java/org/sonar/server/platform/PersistentSettings.java
index a79556610c0..bf344e1788c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/PersistentSettings.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/PersistentSettings.java
@@ -34,11 +34,11 @@ import java.util.Map;
*/
public class PersistentSettings implements Startable {
private final PropertiesDao propertiesDao;
- private final ServerSettings settings;
+ private final ServerSettings serverSettings;
- public PersistentSettings(PropertiesDao propertiesDao, ServerSettings settings) {
+ public PersistentSettings(PropertiesDao propertiesDao, ServerSettings serverSettings) {
this.propertiesDao = propertiesDao;
- this.settings = settings;
+ this.serverSettings = serverSettings;
}
@Override
@@ -47,7 +47,7 @@ public class PersistentSettings implements Startable {
for (PropertyDto property : getGlobalProperties()) {
databaseProperties.put(property.getKey(), property.getValue());
}
- settings.activateDatabaseSettings(databaseProperties);
+ serverSettings.activateDatabaseSettings(databaseProperties);
}
@Override
@@ -56,39 +56,39 @@ public class PersistentSettings implements Startable {
}
public PersistentSettings saveProperty(String key, @Nullable String value) {
- settings.setProperty(key, value);
+ serverSettings.setProperty(key, value);
propertiesDao.insertProperty(new PropertyDto().setKey(key).setValue(value));
return this;
}
public PersistentSettings deleteProperty(String key) {
- settings.removeProperty(key);
+ serverSettings.removeProperty(key);
propertiesDao.deleteGlobalProperty(key);
return this;
}
public PersistentSettings deleteProperties() {
- settings.clear();
+ serverSettings.clear();
propertiesDao.deleteGlobalProperties();
return this;
}
public PersistentSettings saveProperties(Map<String, String> properties) {
- settings.addProperties(properties);
+ serverSettings.addProperties(properties);
propertiesDao.insertGlobalProperties(properties);
return this;
}
public String getString(String key) {
- return settings.getString(key);
+ return serverSettings.getString(key);
}
public Map<String, String> getProperties() {
- return settings.getProperties();
+ return serverSettings.getProperties();
}
public Settings getSettings() {
- return settings;
+ return serverSettings.getSettings();
}
public List<PropertyDto> getGlobalProperties() {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerSettings.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerSettings.java
index 7f569052a86..36ea1473763 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerSettings.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerSettings.java
@@ -19,48 +19,50 @@
*/
package org.sonar.server.platform;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.config.Settings;
-
-import java.util.Collections;
import java.util.Map;
-import java.util.Properties;
+import org.sonar.api.config.Settings;
/**
- * Load settings in the following order (the last override the first) :
- * <ol>
- * <li>general settings persisted in database</li>
- * <li>file $SONAR_HOME/conf/sonar.properties</li>
- * <li>environment variables</li>
- * <li>system properties</li>
- * </ol>
- *
- * @since 2.12
+ * Defines some of the methods of {@link Settings} plus some specific to load db properties on the server side
+ * (see {@link PersistentSettings}).
*/
-public class ServerSettings extends Settings {
+public interface ServerSettings {
+ ServerSettings activateDatabaseSettings(Map<String, String> databaseProperties);
+
+ Settings getSettings();
+
+ /**
+ * @see Settings#getString(String)
+ */
+ String getString(String key);
- private final Properties properties;
+ /**
+ * @see Settings#getProperties()
+ */
+ Map<String, String> getProperties();
- public ServerSettings(PropertyDefinitions definitions, Properties properties) {
- super(definitions);
- this.properties = properties;
- load(Collections.<String, String>emptyMap());
- // Secret key is loaded from conf/sonar.properties
- getEncryption().setPathToSecretKey(getString(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
- }
+ /**
+ * @see Settings#hasKey(String)
+ */
+ boolean hasKey(String foo);
- public ServerSettings activateDatabaseSettings(Map<String, String> databaseProperties) {
- return load(databaseProperties);
- }
+ /**
+ * @see Settings#setProperty(String, String)
+ */
+ Settings setProperty(String key, String value);
- private ServerSettings load(Map<String, String> databaseSettings) {
- clear();
+ /**
+ * @see Settings#removeProperty(String)
+ */
+ Settings removeProperty(String key);
- // order is important : the last override the first
- addProperties(databaseSettings);
- addProperties(properties);
+ /**
+ * @see Settings#clear()
+ */
+ Settings clear();
- return this;
- }
+ /**
+ * @see Settings#addProperties(Map)
+ */
+ Settings addProperties(Map<String, String> properties);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/WebServerSettings.java b/server/sonar-server/src/main/java/org/sonar/server/platform/WebServerSettings.java
new file mode 100644
index 00000000000..7a74f92318c
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/WebServerSettings.java
@@ -0,0 +1,72 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform;
+
+import org.sonar.api.CoreProperties;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Load settings in the following order (the last override the first) :
+ * <ol>
+ * <li>general settings persisted in database</li>
+ * <li>file $SONAR_HOME/conf/sonar.properties</li>
+ * <li>environment variables</li>
+ * <li>system properties</li>
+ * </ol>
+ *
+ * @since 2.12
+ */
+public class WebServerSettings extends Settings implements ServerSettings {
+
+ private final Properties properties;
+
+ public WebServerSettings(PropertyDefinitions definitions, Properties properties) {
+ super(definitions);
+ this.properties = properties;
+ load(Collections.<String, String>emptyMap());
+ // Secret key is loaded from conf/sonar.properties
+ getEncryption().setPathToSecretKey(getString(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
+ }
+
+ @Override
+ public ServerSettings activateDatabaseSettings(Map<String, String> databaseProperties) {
+ return load(databaseProperties);
+ }
+
+ @Override
+ public Settings getSettings() {
+ return this;
+ }
+
+ private ServerSettings load(Map<String, String> databaseSettings) {
+ clear();
+
+ // order is important : the last override the first
+ addProperties(databaseSettings);
+ addProperties(properties);
+
+ return this;
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java
index 9a3b3ae3fe5..ae0469e3237 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java
@@ -42,7 +42,7 @@ import org.sonar.server.platform.DatabaseServerCompatibility;
import org.sonar.server.platform.DefaultServerFileSystem;
import org.sonar.server.platform.Platform;
import org.sonar.server.platform.ServerImpl;
-import org.sonar.server.platform.ServerSettings;
+import org.sonar.server.platform.WebServerSettings;
import org.sonar.server.platform.TempFolderProvider;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
import org.sonar.server.ruby.PlatformRackBridge;
@@ -70,7 +70,7 @@ public class PlatformLevel1 extends PlatformLevel {
add(
new SonarQubeVersionProvider(),
ProcessCommandWrapperImpl.class,
- ServerSettings.class,
+ WebServerSettings.class,
ServerImpl.class,
UuidFactoryImpl.INSTANCE,
EmbeddedDatabaseFactory.class,
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java
index b9ecd37cdec..b9440a08816 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/template/SetDefaultTemplateActionTest.java
@@ -44,7 +44,7 @@ import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.i18n.I18nRule;
import org.sonar.server.permission.ws.PermissionDependenciesFinder;
import org.sonar.server.platform.PersistentSettings;
-import org.sonar.server.platform.ServerSettings;
+import org.sonar.server.platform.WebServerSettings;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.usergroups.ws.UserGroupFinder;
import org.sonar.server.ws.TestRequest;
@@ -82,7 +82,7 @@ public class SetDefaultTemplateActionTest {
@Before
public void setUp() {
DbClient dbClient = db.getDbClient();
- persistentSettings = new PersistentSettings(dbClient.propertiesDao(), new ServerSettings(new PropertyDefinitions(), new Properties()));
+ persistentSettings = new PersistentSettings(dbClient.propertiesDao(), new WebServerSettings(new PropertyDefinitions(), new Properties()));
persistentSettings.saveProperty(DEFAULT_TEMPLATE_PROPERTY, "any-template-uuid");
persistentSettings.saveProperty(defaultRootQualifierTemplateProperty(PROJECT), "any-template-uuid");
persistentSettings.saveProperty(defaultRootQualifierTemplateProperty(VIEW), "any-view-template-uuid");
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/PersistentSettingsTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/PersistentSettingsTest.java
index 7be68d5fed3..0dc3f8c1d4e 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/PersistentSettingsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/PersistentSettingsTest.java
@@ -45,7 +45,7 @@ public class PersistentSettingsTest {
public void init() {
dao = mock(PropertiesDao.class);
- settings = new ServerSettings(
+ settings = new WebServerSettings(
new PropertyDefinitions(),
new Properties());
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/platform/ServerSettingsTest.java b/server/sonar-server/src/test/java/org/sonar/server/platform/ServerSettingsTest.java
index 35fdfd6ddc6..7e2aef09679 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/platform/ServerSettingsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/platform/ServerSettingsTest.java
@@ -33,7 +33,7 @@ public class ServerSettingsTest {
Properties properties;
- ServerSettings settings;
+ WebServerSettings settings;
@Before
public void before() {
@@ -41,7 +41,7 @@ public class ServerSettingsTest {
properties.put("hello", "world");
properties.put("in_file", "true");
properties.put("ServerSettingsTestEnv", "in_file");
- settings = new ServerSettings(new PropertyDefinitions(), properties);
+ settings = new WebServerSettings(new PropertyDefinitions(), properties);
}
@Test
diff --git a/sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java b/sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java
index 5162e6a8d40..597311caf07 100644
--- a/sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java
+++ b/sonar-core/src/main/java/org/sonar/core/platform/ComponentContainer.java
@@ -90,10 +90,15 @@ public class ComponentContainer implements ContainerPopulator.Container {
}
protected ComponentContainer(MutablePicoContainer picoContainer) {
+ this(picoContainer, new PropertyDefinitions());
+ }
+
+ protected ComponentContainer(MutablePicoContainer picoContainer, PropertyDefinitions propertyDefinitions) {
+ requireNonNull(propertyDefinitions, "PropertyDefinitions can not be null");
this.parent = null;
this.pico = picoContainer;
this.componentKeys = new ComponentKeys();
- propertyDefinitions = new PropertyDefinitions();
+ this.propertyDefinitions = propertyDefinitions;
addSingleton(propertyDefinitions);
addSingleton(this);
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java
index 3beb0a9aced..fc5100ce2c4 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java
@@ -110,9 +110,9 @@ public class Settings {
* @since 3.1
*/
public Settings(Settings other) {
- this.properties = Maps.newHashMap(other.properties);
- this.definitions = other.definitions;
- this.encryption = other.encryption;
+ this.properties = Maps.newHashMap(other.getProperties());
+ this.definitions = other.getDefinitions();
+ this.encryption = other.getEncryption();
}
public Encryption getEncryption() {