aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-plugin-api/src/main/java/org/sonar/api/config
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2017-06-29 15:08:28 +0200
committerJulien HENRY <julien.henry@sonarsource.com>2017-07-04 23:47:46 +0200
commit875e23e29f4ed2d41146d8bba8b22448b23df113 (patch)
treee100819edca0bc4c2d75adce8ba760f4fef87059 /sonar-plugin-api/src/main/java/org/sonar/api/config
parentd7f436725b0172217ff8156f1425b4a4a702529c (diff)
downloadsonarqube-875e23e29f4ed2d41146d8bba8b22448b23df113.tar.gz
sonarqube-875e23e29f4ed2d41146d8bba8b22448b23df113.zip
SONAR-9478 Deprecate Settings and introduce new Configuration interface
Diffstat (limited to 'sonar-plugin-api/src/main/java/org/sonar/api/config')
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/config/Configuration.java183
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/config/EmailSettings.java4
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinition.java2
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java1
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java60
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java52
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MapSettings.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/config/MapSettings.java)18
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/config/internal/package-info.java23
8 files changed, 281 insertions, 62 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/Configuration.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/Configuration.java
new file mode 100644
index 00000000000..f91996a0734
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/Configuration.java
@@ -0,0 +1,183 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info 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.api.config;
+
+import java.util.Optional;
+import org.sonar.api.batch.ScannerSide;
+import org.sonar.api.ce.ComputeEngineSide;
+import org.sonar.api.config.internal.MapSettings;
+import org.sonar.api.server.ServerSide;
+import org.sonarsource.api.sonarlint.SonarLintSide;
+
+/**
+ * Component to get effective configuration. Values of properties depend on the runtime environment:
+ * <ul>
+ * <li>immutable project or module configuration in scanner.</li>
+ * <li>global configuration in web server. It does not allow to get the settings overridden on projects.</li>
+ * <li>project configuration in Compute Engine.</li>
+ * </ul>
+ *
+ * <h3>Usage</h3>
+ * <pre>
+ * public class MyExtension {
+ *
+ * private final Configuration config;
+ *
+ * public MyExtension(Configuration config) {
+ * this.config = config;
+ * }
+ * public void doSomething() {
+ * String fooValue = config.get("sonar.foo").orElse(null);
+ * // ..
+ * }
+ * }
+ * </pre>
+ *
+ * <h3>Scanner example</h3>
+ * Scanner sensor can get the reference on Configuration directly through SensorContext,
+ * without injecting the component into constructor.
+ *
+ * <pre>
+ * public class MySensor implements Sensor {
+ * {@literal @}Override
+ * public void execute(SensorContext context) {
+ * String fooValue = context.config().get("sonar.foo").orElse(null);
+ * // ..
+ * }
+ * }
+ * </pre>
+ *
+ * <p>
+ * For testing, and only for testing, the in-memory implementation {@link MapSettings} can be used.
+ * <pre>
+ * {@literal @}Test
+ * public void my_test() {
+ * MapSettings settings = new MapSettings();
+ * settings.setProperty("foo", "bar");
+ * MyExtension underTest = new MyExtension(settings.asConfig());
+ * // ...
+ * }
+ * </pre>
+ *
+ * @see MapSettings
+ * @see PropertyDefinition
+ * @since 6.5
+ */
+@ScannerSide
+@ServerSide
+@ComputeEngineSide
+@SonarLintSide
+public interface Configuration {
+
+ /**
+ * The effective value of the specified property. Can return {@code Optional#empty()} if the property is not set and has no defined default value.
+ * <p>
+ * If the property is encrypted with a secret key, then the returned value is decrypted.
+ * </p>
+ *
+ * @throws IllegalStateException if value is encrypted but fails to be decrypted.
+ */
+ Optional<String> get(String key);
+
+ /**
+ * @return {@code true} if the property has a non-default value, else {@code false}.
+ */
+ boolean hasKey(String key);
+
+ /**
+ * Used to read multi-valued properties.
+ * <p>
+ * See {@link PropertyDefinition.Builder#multiValues(boolean)}
+ * Multi-valued properties coming from scanner are parsed as CSV lines (ie comma separator and optional double quotes to escape values).
+ * Non quoted values are trimmed.
+ * <br>
+ * Examples :
+ * <ul>
+ * <li>"one,two,three " -&gt; ["one", "two", "three"]</li>
+ * <li>" one, two, three " -&gt; ["one", "two", "three"]</li>
+ * <li>"one, , three" -&gt; ["one", "", "three"]</li>
+ * <li>"one,\"two,three\",\" four \"" -&gt; ["one", "two,three", " four "]</li>
+ * </ul>
+ */
+ String[] getStringArray(String key);
+
+ /**
+ * Effective value as boolean. It is {@code empty} if {@link #get(String)} is empty or if it
+ * does not return {@code "true"}, even if it's not a boolean representation.
+ * @return {@code true} if the effective value is {@code "true"}, {@code false} for any other non empty value.
+ * If the property does not have value nor default value, then {@code empty} is returned.
+ */
+ default Optional<Boolean> getBoolean(String key) {
+ return get(key).map(Boolean::parseBoolean);
+ }
+
+ /**
+ * Effective value as {@code int}.
+ * @return the value as {@code int}. If the property does not have value nor default value, then {@code empty} is returned.
+ * @throws NumberFormatException if value is not empty and is not a parsable integer
+ */
+ default Optional<Integer> getInt(String key) {
+ try {
+ return get(key).map(Integer::parseInt);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException(String.format("The property '%s' is not an int value: %s", key, e.getMessage()));
+ }
+ }
+
+ /**
+ * Effective value as {@code long}.
+ * @return the value as {@code long}. If the property does not have value nor default value, then {@code empty} is returned.
+ * @throws NumberFormatException if value is not empty and is not a parsable {@code long}
+ */
+ default Optional<Long> getLong(String key) {
+ try {
+ return get(key).map(Long::parseLong);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException(String.format("The property '%s' is not an long value: %s", key, e.getMessage()));
+ }
+ }
+
+ /**
+ * Effective value as {@code Float}.
+ * @return the value as {@code Float}. If the property does not have value nor default value, then {@code empty} is returned.
+ * @throws NumberFormatException if value is not empty and is not a parsable number
+ */
+ default Optional<Float> getFloat(String key) {
+ try {
+ return get(key).map(Float::valueOf);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException(String.format("The property '%s' is not an float value: %s", key, e.getMessage()));
+ }
+ }
+
+ /**
+ * Effective value as {@code Double}.
+ * @return the value as {@code Double}. If the property does not have value nor default value, then {@code empty} is returned.
+ * @throws NumberFormatException if value is not empty and is not a parsable number
+ */
+ default Optional<Double> getDouble(String key) {
+ try {
+ return get(key).map(Double::valueOf);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException(String.format("The property '%s' is not an double value: %s", key, e.getMessage()));
+ }
+ }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/EmailSettings.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/EmailSettings.java
index dc449884522..dae2594593a 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/config/EmailSettings.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/EmailSettings.java
@@ -21,7 +21,6 @@ package org.sonar.api.config;
import java.util.List;
import org.sonar.api.PropertyType;
-import org.sonar.api.batch.ScannerSide;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
@@ -34,11 +33,8 @@ import static org.sonar.api.PropertyType.INTEGER;
import static org.sonar.api.PropertyType.SINGLE_SELECT_LIST;
/**
- * If batch extensions use this component, then batch must be executed with administrator rights (see properties sonar.login and sonar.password)
- *
* @since 3.2
*/
-@ScannerSide
@ServerSide
@ComputeEngineSide
public class EmailSettings {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinition.java
index 02d64853e8e..13c407d000b 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinition.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinition.java
@@ -57,7 +57,7 @@ import static org.sonar.api.PropertyType.REGULAR_EXPRESSION;
import static org.sonar.api.PropertyType.SINGLE_SELECT_LIST;
/**
- * Declare a plugin property. Values are available at runtime through the component {@link Settings}.
+ * Declare a plugin property. Values are available at runtime through the components {@link Settings} or {@link org.sonar.api.Configuration.SettingsReader}.
* <br>
* It's the programmatic alternative to the annotation {@link org.sonar.api.Property}. It is more
* testable and adds new features like sub-categories and ordering.
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java
index 9a0834b62be..b0e5275674f 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java
@@ -165,6 +165,7 @@ public final class PropertyDefinitions {
return byCategory;
}
+ @CheckForNull
public String getDefaultValue(String key) {
PropertyDefinition def = get(key);
if (def == null) {
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 7e182dcd555..20fb15bff45 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
@@ -35,69 +35,19 @@ import org.sonar.api.batch.ScannerSide;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
import org.sonar.api.utils.DateUtils;
+import org.sonarsource.api.sonarlint.SonarLintSide;
import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang.StringUtils.trim;
/**
- * Component to get effective settings. Values of properties depend on the runtime environment:
- * <ul>
- * <li>project settings in scanner.</li>
- * <li>global settings in web server. It does not allow to get the settings overridden on projects.</li>
- * <li>project settings in Compute Engine.</li>
- * </ul>
- *
- * <h3>Usage</h3>
- * <pre>
- * public class MyExtension {
- *
- * private final Settings settings;
- *
- * public MyExtension(Settings settings) {
- * this.settings = settings;
- * }
- * public void doSomething() {
- * String fooValue = settings.getString("sonar.foo");
- * // ..
- * }
- * }
- * </pre>
- *
- * <h3>Scanner example</h3>
- * Scanner sensor can get the reference on Settings directly through SensorContext,
- * without injecting the component into constructor.
- *
- * <pre>
- * public class MySensor implements Sensor {
- * {@literal @}Override
- * public void execute(SensorContext context) {
- * String fooValue = context.settings().getString("sonar.foo");
- * // ..
- * }
- * }
- * </pre>
- *
- * <p>
- * For testing, and only for testing, the in-memory implementation {@link MapSettings} can be used.
- * <pre>
- * {@literal @}Test
- * public void my_test() {
- * Settings settings = new MapSettings();
- * settings.setProperty("foo", "bar");
- * MyExtension underTest = new MyExtension(settings);
- * // ...
- * }
- * </pre>
- *
- * History - this class is abstract since 6.1.
- *
- * @see MapSettings
- * @see PropertyDefinition
- * @since 2.12
+ * @deprecated since 6.5 use {@link Configuration}
*/
-@ScannerSide
@ServerSide
@ComputeEngineSide
+@ScannerSide
+@SonarLintSide
+@Deprecated
public abstract class Settings {
private final PropertyDefinitions definitions;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java
new file mode 100644
index 00000000000..4e8ef584fd3
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java
@@ -0,0 +1,52 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info 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.api.config.internal;
+
+import java.util.Optional;
+import org.sonar.api.config.Settings;
+import org.sonar.api.config.Configuration;
+
+/**
+ * Used to help migration from {@link Settings} to {@link Configuration}
+ */
+public class ConfigurationBridge implements Configuration {
+
+ private final Settings settings;
+
+ public ConfigurationBridge(Settings settings) {
+ this.settings = settings;
+ }
+
+ @Override
+ public Optional<String> get(String key) {
+ return Optional.ofNullable(settings.getString(key));
+ }
+
+ @Override
+ public boolean hasKey(String key) {
+ return settings.hasKey(key);
+ }
+
+ @Override
+ public String[] getStringArray(String key) {
+ return settings.getStringArray(key);
+ }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/MapSettings.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MapSettings.java
index 5a73567a808..6d45e12ddb6 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/config/MapSettings.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MapSettings.java
@@ -17,11 +17,15 @@
* 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.api.config;
+package org.sonar.api.config.internal;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
+import org.sonar.api.config.Configuration;
+import org.sonar.api.config.Encryption;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
import static java.util.Collections.unmodifiableMap;
@@ -36,13 +40,15 @@ import static java.util.Collections.unmodifiableMap;
public class MapSettings extends Settings {
private final Map<String, String> props = new HashMap<>();
+ private final ConfigurationBridge configurationBridge;
public MapSettings() {
- super(new PropertyDefinitions(), new Encryption(null));
+ this(new PropertyDefinitions());
}
public MapSettings(PropertyDefinitions definitions) {
super(definitions, new Encryption(null));
+ configurationBridge = new ConfigurationBridge(this);
}
@Override
@@ -72,4 +78,12 @@ public class MapSettings extends Settings {
props.clear();
return this;
}
+
+ /**
+ * @return a {@link Configuration} proxy on top of this existing {@link Settings} implementation. Changes are reflected in the {@link Configuration} object.
+ * @since 6.5
+ */
+ public Configuration asConfig() {
+ return configurationBridge;
+ }
}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/package-info.java
new file mode 100644
index 00000000000..4fb297e0a30
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2017 SonarSource SA
+ * mailto:info 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.api.config.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault;