diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2017-06-29 15:08:28 +0200 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2017-07-04 23:47:46 +0200 |
commit | 875e23e29f4ed2d41146d8bba8b22448b23df113 (patch) | |
tree | e100819edca0bc4c2d75adce8ba760f4fef87059 /sonar-plugin-api/src/main/java/org/sonar/api/config | |
parent | d7f436725b0172217ff8156f1425b4a4a702529c (diff) | |
download | sonarqube-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.java | 183 | ||||
-rw-r--r-- | sonar-plugin-api/src/main/java/org/sonar/api/config/EmailSettings.java | 4 | ||||
-rw-r--r-- | sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinition.java | 2 | ||||
-rw-r--r-- | sonar-plugin-api/src/main/java/org/sonar/api/config/PropertyDefinitions.java | 1 | ||||
-rw-r--r-- | sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java | 60 | ||||
-rw-r--r-- | sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java | 52 | ||||
-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.java | 23 |
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 " -> ["one", "two", "three"]</li> + * <li>" one, two, three " -> ["one", "two", "three"]</li> + * <li>"one, , three" -> ["one", "", "three"]</li> + * <li>"one,\"two,three\",\" four \"" -> ["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; |