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 | |
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')
22 files changed, 344 insertions, 97 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/Properties.java b/sonar-plugin-api/src/main/java/org/sonar/api/Properties.java index 9efca22299a..c38f1ecc257 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/Properties.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/Properties.java @@ -21,6 +21,7 @@ package org.sonar.api; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import org.sonar.api.config.Configuration; /** * Plugin properties. This annotation is only used on classes implementing org.sonar.api.Plugin. @@ -28,7 +29,7 @@ import java.lang.annotation.RetentionPolicy; * Note that {@link org.sonar.api.config.PropertyDefinition} is an alternative, programmatic and recommended approach * to declare properties. * <br> - * Effective property values are accessible at runtime through the component {@link org.sonar.api.config.Settings} + * Effective property values are accessible at runtime through the component {@link Configuration} * * @since 1.10 */ diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java index 74cad4f2ae6..9bf8eef05b4 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java @@ -186,7 +186,7 @@ public class ProjectDefinition { } return null; } - + @CheckForNull public String getOriginalVersion() { return properties.get(CoreProperties.PROJECT_VERSION_PROPERTY); @@ -199,7 +199,7 @@ public class ProjectDefinition { } return version; } - + @CheckForNull public String getOriginalName() { return properties.get(CoreProperties.PROJECT_NAME_PROPERTY); @@ -320,6 +320,7 @@ public class ProjectDefinition { return this; } + @CheckForNull public ProjectDefinition getParent() { return parent; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/debt/DebtRemediationFunction.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/debt/DebtRemediationFunction.java index 44917519e72..96ff255364c 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/debt/DebtRemediationFunction.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/debt/DebtRemediationFunction.java @@ -25,6 +25,7 @@ import org.sonar.api.utils.Duration; /** * @since 4.3 + * @deprecated since 6.5 debt model will soon be unavailable on batch side */ public class DebtRemediationFunction { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJobContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJobContext.java index 2baa34478d2..cfe881f2866 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJobContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/postjob/PostJobContext.java @@ -21,6 +21,7 @@ package org.sonar.api.batch.postjob; import org.sonar.api.batch.AnalysisMode; import org.sonar.api.batch.postjob.issue.PostJobIssue; +import org.sonar.api.config.Configuration; import org.sonar.api.config.Settings; /** @@ -30,10 +31,16 @@ import org.sonar.api.config.Settings; public interface PostJobContext { /** - * Get settings of the current project. + * @deprecated since 6.5 use {@link PostJobContext#config()} */ Settings settings(); + /** + * Get configuration of the current project. + * @since 6.5 + */ + Configuration config(); + AnalysisMode analysisMode(); // ----------- Only available in preview mode -------------- diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java index f47c408ccf0..8da60fb974e 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/SensorContext.java @@ -24,6 +24,7 @@ import org.sonar.api.SonarRuntime; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputModule; +import org.sonar.api.batch.postjob.PostJobContext; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.sensor.coverage.NewCoverage; import org.sonar.api.batch.sensor.cpd.NewCpdTokens; @@ -36,6 +37,7 @@ import org.sonar.api.batch.sensor.measure.Measure; import org.sonar.api.batch.sensor.measure.NewMeasure; import org.sonar.api.batch.sensor.symbol.NewSymbolTable; import org.sonar.api.config.Settings; +import org.sonar.api.config.Configuration; import org.sonar.api.utils.Version; /** @@ -46,11 +48,17 @@ import org.sonar.api.utils.Version; public interface SensorContext { /** - * Get settings of the current module. + * @deprecated since 6.5 use {@link PostJobContext#config()} */ Settings settings(); /** + * Get settings of the current module, or of the project for a global Sensor. + * @since 6.5 + */ + Configuration config(); + + /** * Get filesystem of the current module. */ FileSystem fileSystem(); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java index 3ff672988da..abdb03c9ecc 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java @@ -28,7 +28,7 @@ import org.sonar.api.batch.fs.internal.PathPattern; import org.sonar.api.batch.sensor.cpd.NewCpdTokens; import org.sonar.api.batch.sensor.internal.DefaultStorable; import org.sonar.api.batch.sensor.internal.SensorStorage; -import org.sonar.api.config.Settings; +import org.sonar.api.config.Configuration; import org.sonar.duplications.internal.pmd.TokensLine; import static com.google.common.base.Preconditions.checkState; @@ -37,7 +37,7 @@ import static java.util.Objects.requireNonNull; public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens { - private final Settings settings; + private final Configuration config; private final ArrayList<TokensLine> result = new ArrayList<>(); private InputFile inputFile; private int startLine = Integer.MIN_VALUE; @@ -47,15 +47,15 @@ public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens { private TextRange lastRange; private boolean excluded; - public DefaultCpdTokens(Settings settings, SensorStorage storage) { + public DefaultCpdTokens(Configuration config, SensorStorage storage) { super(storage); - this.settings = settings; + this.config = config; } @Override public DefaultCpdTokens onFile(InputFile inputFile) { this.inputFile = requireNonNull(inputFile, "file can't be null"); - String[] cpdExclusions = settings.getStringArray(CoreProperties.CPD_EXCLUSIONS); + String[] cpdExclusions = config.getStringArray(CoreProperties.CPD_EXCLUSIONS); for (PathPattern cpdExclusion : PathPattern.create(cpdExclusions)) { if (cpdExclusion.match(inputFile)) { this.excluded = true; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java index 4a3d60763ec..711821e7909 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java @@ -64,8 +64,10 @@ import org.sonar.api.batch.sensor.measure.NewMeasure; import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; import org.sonar.api.batch.sensor.symbol.NewSymbolTable; import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable; -import org.sonar.api.config.MapSettings; +import org.sonar.api.config.Configuration; import org.sonar.api.config.Settings; +import org.sonar.api.config.internal.ConfigurationBridge; +import org.sonar.api.config.internal.MapSettings; import org.sonar.api.internal.ApiVersion; import org.sonar.api.internal.SonarRuntimeImpl; import org.sonar.api.measures.Metric; @@ -122,6 +124,11 @@ public class SensorContextTester implements SensorContext { return settings; } + @Override + public Configuration config() { + return new ConfigurationBridge(settings); + } + public SensorContextTester setSettings(Settings settings) { this.settings = settings; return this; @@ -269,7 +276,7 @@ public class SensorContextTester implements SensorContext { @Override public NewCpdTokens newCpdTokens() { - return new DefaultCpdTokens(settings, sensorStorage); + return new DefaultCpdTokens(config(), sensorStorage); } @Override 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; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileExclusions.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileExclusions.java index 1a071e62758..af7e9550b96 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileExclusions.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/filesystem/FileExclusions.java @@ -24,7 +24,7 @@ import java.util.stream.Stream; import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; import org.sonar.api.batch.ScannerSide; -import org.sonar.api.config.Settings; +import org.sonar.api.config.Configuration; /** * Configuration of file inclusions and exclusions. @@ -35,9 +35,9 @@ import org.sonar.api.config.Settings; */ @ScannerSide public class FileExclusions { - private final Settings settings; + private final Configuration settings; - public FileExclusions(Settings settings) { + public FileExclusions(Configuration settings) { this.settings = settings; } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectBuilderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectBuilderTest.java index b8b08a4e4dc..72fd4a8539c 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectBuilderTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectBuilderTest.java @@ -23,7 +23,7 @@ import java.io.File; import org.junit.Test; import org.sonar.api.batch.bootstrap.internal.ProjectBuilderContext; import org.sonar.api.config.Settings; -import org.sonar.api.config.MapSettings; +import org.sonar.api.config.internal.MapSettings; import static org.assertj.core.api.Assertions.assertThat; import static org.hamcrest.core.Is.is; diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokensTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokensTest.java index 9b20b94d700..62a268f00f7 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokensTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokensTest.java @@ -24,7 +24,7 @@ import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.api.batch.sensor.internal.SensorStorage; import org.sonar.api.config.Settings; -import org.sonar.api.config.MapSettings; +import org.sonar.api.config.internal.MapSettings; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; @@ -44,7 +44,7 @@ public class DefaultCpdTokensTest { @Test public void save_no_tokens() { SensorStorage sensorStorage = mock(SensorStorage.class); - DefaultCpdTokens tokens = new DefaultCpdTokens(new MapSettings(), sensorStorage) + DefaultCpdTokens tokens = new DefaultCpdTokens(new MapSettings().asConfig(), sensorStorage) .onFile(INPUT_FILE); tokens.save(); @@ -57,7 +57,7 @@ public class DefaultCpdTokensTest { @Test public void save_one_token() { SensorStorage sensorStorage = mock(SensorStorage.class); - DefaultCpdTokens tokens = new DefaultCpdTokens(new MapSettings(), sensorStorage) + DefaultCpdTokens tokens = new DefaultCpdTokens(new MapSettings().asConfig(), sensorStorage) .onFile(INPUT_FILE) .addToken(INPUT_FILE.newRange(1, 2, 1, 5), "foo"); @@ -71,9 +71,9 @@ public class DefaultCpdTokensTest { @Test public void handle_exclusions_by_pattern() { SensorStorage sensorStorage = mock(SensorStorage.class); - Settings settings = new MapSettings(); + MapSettings settings = new MapSettings(); settings.setProperty("sonar.cpd.exclusions", "src/Foo.java,another"); - DefaultCpdTokens tokens = new DefaultCpdTokens(settings, sensorStorage) + DefaultCpdTokens tokens = new DefaultCpdTokens(settings.asConfig(), sensorStorage) .onFile(INPUT_FILE) .addToken(INPUT_FILE.newRange(1, 2, 1, 5), "foo"); @@ -87,7 +87,7 @@ public class DefaultCpdTokensTest { @Test public void save_many_tokens() { SensorStorage sensorStorage = mock(SensorStorage.class); - DefaultCpdTokens tokens = new DefaultCpdTokens(new MapSettings(), sensorStorage) + DefaultCpdTokens tokens = new DefaultCpdTokens(new MapSettings().asConfig(), sensorStorage) .onFile(INPUT_FILE) .addToken(INPUT_FILE.newRange(1, 2, 1, 5), "foo") .addToken(INPUT_FILE.newRange(1, 6, 1, 10), "bar") @@ -108,7 +108,7 @@ public class DefaultCpdTokensTest { @Test public void basic_validation() { SensorStorage sensorStorage = mock(SensorStorage.class); - DefaultCpdTokens tokens = new DefaultCpdTokens(new MapSettings(), sensorStorage); + DefaultCpdTokens tokens = new DefaultCpdTokens(new MapSettings().asConfig(), sensorStorage); try { tokens.save(); fail("Expected exception"); @@ -138,7 +138,7 @@ public class DefaultCpdTokensTest { @Test public void validate_tokens_order() { SensorStorage sensorStorage = mock(SensorStorage.class); - DefaultCpdTokens tokens = new DefaultCpdTokens(new MapSettings(), sensorStorage) + DefaultCpdTokens tokens = new DefaultCpdTokens(new MapSettings().asConfig(), sensorStorage) .onFile(INPUT_FILE) .addToken(INPUT_FILE.newRange(1, 6, 1, 10), "bar"); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java index 4893f6fdd63..566facb4a1a 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/sensor/internal/SensorContextTesterTest.java @@ -38,8 +38,8 @@ import org.sonar.api.batch.sensor.error.NewAnalysisError; import org.sonar.api.batch.sensor.highlighting.TypeOfText; import org.sonar.api.batch.sensor.issue.NewIssue; import org.sonar.api.batch.sensor.symbol.NewSymbolTable; -import org.sonar.api.config.MapSettings; import org.sonar.api.config.Settings; +import org.sonar.api.config.internal.MapSettings; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.SonarException; diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/config/EmailSettingsTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/config/EmailSettingsTest.java index b5504b5d2b3..507ab123b08 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/config/EmailSettingsTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/config/EmailSettingsTest.java @@ -21,6 +21,7 @@ package org.sonar.api.config; import org.junit.Test; import org.sonar.api.CoreProperties; +import org.sonar.api.config.internal.MapSettings; import static org.assertj.core.api.Assertions.assertThat; diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/config/MapSettingsTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/config/internal/MapSettingsTest.java index 284d35ea507..e28a73cdb9c 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/config/MapSettingsTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/config/internal/MapSettingsTest.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.api.config; +package org.sonar.api.config.internal; import java.util.Date; import org.assertj.core.data.Offset; @@ -28,6 +28,9 @@ import org.junit.rules.ExpectedException; import org.sonar.api.Properties; import org.sonar.api.Property; import org.sonar.api.PropertyType; +import org.sonar.api.config.PropertyDefinitions; +import org.sonar.api.config.Settings; +import org.sonar.api.config.internal.MapSettings; import org.sonar.api.utils.DateUtils; import static org.assertj.core.api.Assertions.assertThat; diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/FileExclusionsTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/FileExclusionsTest.java index bd98496fdf9..bd03eec7fed 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/FileExclusionsTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/scan/filesystem/FileExclusionsTest.java @@ -21,27 +21,26 @@ package org.sonar.api.scan.filesystem; import org.junit.Test; import org.sonar.api.CoreProperties; -import org.sonar.api.config.Settings; -import org.sonar.api.config.MapSettings; +import org.sonar.api.config.internal.MapSettings; import static org.assertj.core.api.Assertions.assertThat; public class FileExclusionsTest { @Test public void ignore_inclusion_of_world() { - Settings settings = new MapSettings(); + MapSettings settings = new MapSettings(); settings.setProperty(CoreProperties.PROJECT_INCLUSIONS_PROPERTY, "**/*"); settings.setProperty(CoreProperties.PROJECT_TEST_INCLUSIONS_PROPERTY, "**/*"); - assertThat(new FileExclusions(settings).sourceInclusions()).isEmpty(); - assertThat(new FileExclusions(settings).testInclusions()).isEmpty(); + assertThat(new FileExclusions(settings.asConfig()).sourceInclusions()).isEmpty(); + assertThat(new FileExclusions(settings.asConfig()).testInclusions()).isEmpty(); } @Test public void load_inclusions() { - Settings settings = new MapSettings(); + MapSettings settings = new MapSettings(); settings.setProperty(CoreProperties.PROJECT_INCLUSIONS_PROPERTY, "**/*Foo.java"); settings.setProperty(CoreProperties.PROJECT_TEST_INCLUSIONS_PROPERTY, "**/*FooTest.java"); - FileExclusions moduleExclusions = new FileExclusions(settings); + FileExclusions moduleExclusions = new FileExclusions(settings.asConfig()); assertThat(moduleExclusions.sourceInclusions()).containsOnly("**/*Foo.java"); assertThat(moduleExclusions.testInclusions()).containsOnly("**/*FooTest.java"); @@ -49,10 +48,10 @@ public class FileExclusionsTest { @Test public void load_exclusions() { - Settings settings = new MapSettings(); + MapSettings settings = new MapSettings(); settings.setProperty(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY, "**/*Foo.java"); settings.setProperty(CoreProperties.PROJECT_TEST_EXCLUSIONS_PROPERTY, "**/*FooTest.java"); - FileExclusions moduleExclusions = new FileExclusions(settings); + FileExclusions moduleExclusions = new FileExclusions(settings.asConfig()); assertThat(moduleExclusions.sourceInclusions()).isEmpty(); assertThat(moduleExclusions.sourceExclusions()).containsOnly("**/*Foo.java"); |