From 85672fd49fa3b81eaf07792fb76e03967e85da3d Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Fri, 20 Mar 2020 09:13:40 +0100 Subject: [PATCH] SONAR-13214 Restore a minimal Settings API for backward compatibility --- .../sensor/internal/SensorContextTester.java | 1 + .../sonar/api/config/internal/Settings.java | 27 ++-- .../sonar/api/batch/sensor/SensorContext.java | 7 + .../java/org/sonar/api/config/Settings.java | 147 ++++++++++++++++++ .../scanner/sensor/ModuleSensorContext.java | 5 +- .../scanner/sensor/ProjectSensorContext.java | 10 +- .../sensor/ModuleSensorContextTest.java | 2 +- 7 files changed, 183 insertions(+), 16 deletions(-) create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java index 14806bc4e16..232dd46641e 100644 --- a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java +++ b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java @@ -131,6 +131,7 @@ public class SensorContextTester implements SensorContext { return new SensorContextTester(moduleBaseDir); } + @Override public MapSettings settings() { return settings; } diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/Settings.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/Settings.java index a934a807cb5..247edf5fa32 100644 --- a/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/Settings.java +++ b/sonar-plugin-api-impl/src/main/java/org/sonar/api/config/internal/Settings.java @@ -31,27 +31,17 @@ import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; -import org.sonar.api.ce.ComputeEngineSide; -import org.sonar.api.config.Configuration; import org.sonar.api.config.PropertyDefinition; import org.sonar.api.config.PropertyDefinitions; -import org.sonar.api.scanner.ScannerSide; -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; /** - * @deprecated since 6.5 use {@link Configuration} + * Implementation of the deprecated Settings interface */ -@ServerSide -@ComputeEngineSide -@ScannerSide -@SonarLintSide -@Deprecated -public abstract class Settings { +public abstract class Settings extends org.sonar.api.config.Settings { private final PropertyDefinitions definitions; private final Encryption encryption; @@ -118,6 +108,7 @@ public abstract class Settings { /** * @return {@code true} if the property has a non-default value, else {@code false}. */ + @Override public boolean hasKey(String key) { return getRawString(key).isPresent(); } @@ -143,6 +134,7 @@ public abstract class Settings { * @throws IllegalStateException if value is encrypted but fails to be decrypted. */ @CheckForNull + @Override public String getString(String key) { String effectiveKey = definitions.validKey(key); Optional value = getRawString(effectiveKey); @@ -166,6 +158,7 @@ public abstract class Settings { * * @return {@code true} if the effective value is {@code "true"}, else {@code false}. */ + @Override public boolean getBoolean(String key) { String value = getString(key); return StringUtils.isNotEmpty(value) && Boolean.parseBoolean(value); @@ -177,6 +170,7 @@ public abstract class Settings { * @return the value as {@code int}. If the property does not have value nor default value, then {@code 0} is returned. * @throws NumberFormatException if value is not empty and is not a parsable integer */ + @Override public int getInt(String key) { String value = getString(key); if (StringUtils.isNotEmpty(value)) { @@ -191,6 +185,7 @@ public abstract class Settings { * @return the value as {@code long}. If the property does not have value nor default value, then {@code 0L} is returned. * @throws NumberFormatException if value is not empty and is not a parsable {@code long} */ + @Override public long getLong(String key) { String value = getString(key); if (StringUtils.isNotEmpty(value)) { @@ -206,6 +201,7 @@ public abstract class Settings { * @throws RuntimeException if value is not empty and is not in accordance with {@link DateUtils#DATE_FORMAT}. */ @CheckForNull + @Override public Date getDate(String key) { String value = getString(key); if (StringUtils.isNotEmpty(value)) { @@ -221,6 +217,7 @@ public abstract class Settings { * @throws RuntimeException if value is not empty and is not in accordance with {@link DateUtils#DATETIME_FORMAT}. */ @CheckForNull + @Override public Date getDateTime(String key) { String value = getString(key); if (StringUtils.isNotEmpty(value)) { @@ -236,6 +233,7 @@ public abstract class Settings { * @throws NumberFormatException if value is not empty and is not a parsable number */ @CheckForNull + @Override public Float getFloat(String key) { String value = getString(key); if (StringUtils.isNotEmpty(value)) { @@ -255,6 +253,7 @@ public abstract class Settings { * @throws NumberFormatException if value is not empty and is not a parsable number */ @CheckForNull + @Override public Double getDouble(String key) { String value = getString(key); if (StringUtils.isNotEmpty(value)) { @@ -277,6 +276,7 @@ public abstract class Settings { *
  • "one, , three" -> ["one", "", "three"]
  • * */ + @Override public String[] getStringArray(String key) { String effectiveKey = definitions.validKey(key); Optional def = getDefinition(effectiveKey); @@ -300,6 +300,7 @@ public abstract class Settings { * @return non-null array of lines. The line termination characters are excluded. * @since 3.2 */ + @Override public String[] getStringLines(String key) { String value = getString(key); if (StringUtils.isEmpty(value)) { @@ -311,6 +312,7 @@ public abstract class Settings { /** * Value is split and trimmed. */ + @Override public String[] getStringArrayBySeparator(String key, String separator) { String value = getString(key); if (value != null) { @@ -451,6 +453,7 @@ public abstract class Settings { return this; } + @Override public List getKeysStartingWith(String prefix) { return getProperties().keySet().stream() .filter(key -> StringUtils.startsWith(key, prefix)) 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 038a6dc5f20..b156d2c5480 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 @@ -40,6 +40,7 @@ import org.sonar.api.batch.sensor.rule.AdHocRule; import org.sonar.api.batch.sensor.rule.NewAdHocRule; import org.sonar.api.batch.sensor.symbol.NewSymbolTable; import org.sonar.api.config.Configuration; +import org.sonar.api.config.Settings; import org.sonar.api.scanner.fs.InputProject; import org.sonar.api.scanner.sensor.ProjectSensor; import org.sonar.api.utils.Version; @@ -51,6 +52,12 @@ import org.sonar.api.utils.Version; */ public interface SensorContext { + /** + * @deprecated since 6.5 use {@link #config()} + */ + @Deprecated + Settings settings(); + /** * Get settings of the project. * @since 6.5 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 new file mode 100644 index 00000000000..6effc9a90dc --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java @@ -0,0 +1,147 @@ +/* + * SonarQube + * Copyright (C) 2009-2020 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.Date; +import java.util.List; +import javax.annotation.CheckForNull; +import org.sonar.api.ce.ComputeEngineSide; +import org.sonar.api.scanner.ScannerSide; +import org.sonar.api.server.ServerSide; +import org.sonar.api.utils.DateUtils; +import org.sonarsource.api.sonarlint.SonarLintSide; + +/** + * @deprecated since 6.5 use {@link Configuration}. Implementation moved out of the API in 8.3. Only remains minimal interface to make some outdated plugins happy. + */ +@ServerSide +@ComputeEngineSide +@ScannerSide +@SonarLintSide +@Deprecated +public abstract class Settings { + + /** + * @return {@code true} if the property has a non-default value, else {@code false}. + */ + public abstract boolean hasKey(String key); + + /** + * The effective value of the specified property. Can return + * {@code null} if the property is not set and has no + * defined default value. + *

    + * If the property is encrypted with a secret key, + * then the returned value is decrypted. + *

    + * + * @throws IllegalStateException if value is encrypted but fails to be decrypted. + */ + @CheckForNull + public abstract String getString(String key); + + /** + * Effective value as boolean. It is {@code false} if {@link #getString(String)} + * does not return {@code "true"}, even if it's not a boolean representation. + * + * @return {@code true} if the effective value is {@code "true"}, else {@code false}. + */ + public abstract boolean getBoolean(String key); + + /** + * Effective value as {@code int}. + * + * @return the value as {@code int}. If the property does not have value nor default value, then {@code 0} is returned. + * @throws NumberFormatException if value is not empty and is not a parsable integer + */ + public abstract int getInt(String key); + + /** + * Effective value as {@code long}. + * + * @return the value as {@code long}. If the property does not have value nor default value, then {@code 0L} is returned. + * @throws NumberFormatException if value is not empty and is not a parsable {@code long} + */ + public abstract long getLong(String key); + + /** + * Effective value as {@link Date}, without time fields. Format is {@link DateUtils#DATE_FORMAT}. + * + * @return the value as a {@link Date}. If the property does not have value nor default value, then {@code null} is returned. + * @throws RuntimeException if value is not empty and is not in accordance with {@link DateUtils#DATE_FORMAT}. + */ + @CheckForNull + public abstract Date getDate(String key); + + /** + * Effective value as {@link Date}, with time fields. Format is {@link DateUtils#DATETIME_FORMAT}. + * + * @return the value as a {@link Date}. If the property does not have value nor default value, then {@code null} is returned. + * @throws RuntimeException if value is not empty and is not in accordance with {@link DateUtils#DATETIME_FORMAT}. + */ + @CheckForNull + public abstract Date getDateTime(String key); + + /** + * Effective value as {@code Float}. + * + * @return the value as {@code Float}. If the property does not have value nor default value, then {@code null} is returned. + * @throws NumberFormatException if value is not empty and is not a parsable number + */ + @CheckForNull + public abstract Float getFloat(String key); + + /** + * Effective value as {@code Double}. + * + * @return the value as {@code Double}. If the property does not have value nor default value, then {@code null} is returned. + * @throws NumberFormatException if value is not empty and is not a parsable number + */ + @CheckForNull + public abstract Double getDouble(String key); + + /** + * Value is split by comma and trimmed. Never returns null. + *
    + * Examples : + *
      + *
    • "one,two,three " -> ["one", "two", "three"]
    • + *
    • " one, two, three " -> ["one", "two", "three"]
    • + *
    • "one, , three" -> ["one", "", "three"]
    • + *
    + */ + public abstract String[] getStringArray(String key); + + /** + * Value is split by carriage returns. + * + * @return non-null array of lines. The line termination characters are excluded. + * @since 3.2 + */ + public abstract String[] getStringLines(String key); + + /** + * Value is split and trimmed. + */ + public abstract String[] getStringArrayBySeparator(String key, String separator); + + public abstract List getKeysStartingWith(String prefix); + +} diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorContext.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorContext.java index b82a8d6e037..2a038546266 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorContext.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ModuleSensorContext.java @@ -27,15 +27,16 @@ import org.sonar.api.batch.fs.internal.DefaultInputProject; import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.sensor.internal.SensorStorage; import org.sonar.api.config.Configuration; +import org.sonar.api.config.Settings; @ThreadSafe public class ModuleSensorContext extends ProjectSensorContext { private final InputModule module; - public ModuleSensorContext(DefaultInputProject project, InputModule module, Configuration config, FileSystem fs, ActiveRules activeRules, + public ModuleSensorContext(DefaultInputProject project, InputModule module, Configuration config, Settings mutableSettings, FileSystem fs, ActiveRules activeRules, SensorStorage sensorStorage, SonarRuntime sonarRuntime) { - super(project, config, fs, activeRules, sensorStorage, sonarRuntime); + super(project, config, mutableSettings, fs, activeRules, sensorStorage, sonarRuntime); this.module = module; } diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorContext.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorContext.java index 9819d18c6f1..3e43dc2f8a0 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorContext.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/sensor/ProjectSensorContext.java @@ -50,6 +50,7 @@ import org.sonar.api.batch.sensor.rule.internal.DefaultAdHocRule; import org.sonar.api.batch.sensor.symbol.NewSymbolTable; import org.sonar.api.batch.sensor.symbol.internal.DefaultSymbolTable; import org.sonar.api.config.Configuration; +import org.sonar.api.config.Settings; import org.sonar.api.scanner.fs.InputProject; import org.sonar.api.utils.Version; import org.sonar.scanner.sensor.noop.NoOpNewAnalysisError; @@ -59,6 +60,7 @@ public class ProjectSensorContext implements SensorContext { static final NoOpNewAnalysisError NO_OP_NEW_ANALYSIS_ERROR = new NoOpNewAnalysisError(); + private final Settings mutableSettings; private final FileSystem fs; private final ActiveRules activeRules; private final SensorStorage sensorStorage; @@ -66,16 +68,22 @@ public class ProjectSensorContext implements SensorContext { private final SonarRuntime sonarRuntime; private final Configuration config; - public ProjectSensorContext(DefaultInputProject project, Configuration config, FileSystem fs, ActiveRules activeRules, + public ProjectSensorContext(DefaultInputProject project, Configuration config, Settings mutableSettings, FileSystem fs, ActiveRules activeRules, SensorStorage sensorStorage, SonarRuntime sonarRuntime) { this.project = project; this.config = config; + this.mutableSettings = mutableSettings; this.fs = fs; this.activeRules = activeRules; this.sensorStorage = sensorStorage; this.sonarRuntime = sonarRuntime; } + @Override + public Settings settings() { + return mutableSettings; + } + @Override public Configuration config() { return config; diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorContextTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorContextTest.java index a29e0deb855..66edd4715dc 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorContextTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/sensor/ModuleSensorContextTest.java @@ -68,7 +68,7 @@ public class ModuleSensorContextTest { settings = new MapSettings(); sensorStorage = mock(SensorStorage.class); runtime = SonarRuntimeImpl.forSonarQube(Version.parse("5.5"), SonarQubeSide.SCANNER, SonarEdition.COMMUNITY); - adaptor = new ModuleSensorContext(mock(DefaultInputProject.class), mock(InputModule.class), settings.asConfig(), fs, activeRules, sensorStorage, runtime); + adaptor = new ModuleSensorContext(mock(DefaultInputProject.class), mock(InputModule.class), settings.asConfig(), settings, fs, activeRules, sensorStorage, runtime); } @Test -- 2.39.5