diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-07-27 22:57:19 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-07-27 22:57:19 +0200 |
commit | b710ae53feba2a4d8d2c181a26d5d1163e407d1b (patch) | |
tree | b6c485dd46d35115a0100dbe25d594a4dca8733d /sonar-plugin-api/src | |
parent | e4ba85fe304aaad519e574b8f4e172b733389752 (diff) | |
parent | 85bfbe28689b4276a04eeeed91b205ab76e81d06 (diff) | |
download | sonarqube-b710ae53feba2a4d8d2c181a26d5d1163e407d1b.tar.gz sonarqube-b710ae53feba2a4d8d2c181a26d5d1163e407d1b.zip |
Fix merge of branch-6.0
Diffstat (limited to 'sonar-plugin-api/src')
13 files changed, 285 insertions, 290 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java b/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java index 8fb50a0b14c..965a1b13b01 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/Plugin.java @@ -33,14 +33,13 @@ import static java.util.Objects.requireNonNull; * This property is automatically set by sonar-packaging-maven-plugin when building plugin. * <p>Example of implementation * <pre> - * package com.mycompany.sonarqube; - * public class MyPlugin implements Plugin { + * public class MyPlugin implements Plugin { * {@literal @}Override * public void define(Context context) { * context.addExtensions(MySensor.class, MyRules.class); - * if (context.getSonarQubeVersion().isGreaterThanOrEqual(SonarQubeVersion.V5_6)) { - * // Extension which supports only versions 5.6 and greater - * // See org.sonar.api.SonarQubeVersion for more details. + * if (context.getRuntime().getApiVersion().isGreaterThanOrEqual(Version.create(6, 0))) { + * // Extension which supports only versions 6.0 and greater + * // See org.sonar.api.SonarRuntime for more details. * context.addExtension(MyNewExtension.class); * } * } @@ -73,8 +72,9 @@ import static java.util.Objects.requireNonNull; * MyPlugin underTest = new MyPlugin(); * *{@literal @}Test - * public void test_plugin_extensions_compatible_with_5_5() { - * Plugin.Context context = new Plugin.Context(SonarQubeVersion.V5_5); + * public void test_plugin_extensions_compatible_with_5_6() { + * SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.create(5, 6)); + * Plugin.Context context = new Plugin.Context(runtime); * underTest.define(context); * assertThat(context.getExtensions()).hasSize(4); * } @@ -93,7 +93,7 @@ public interface Plugin { } /** - * @deprecated since 6.0 use {@link #getRuntimeApiVersion()} + * @deprecated replaced by {@link #getRuntime()}.getApiVersion() in 6.0 */ @Deprecated public Version getSonarQubeVersion() { @@ -101,11 +101,11 @@ public interface Plugin { } /** - * Runtime API version. Can be use to conditionnaly add some extensions. + * Runtime environment. Can be use to add some extensions only on some conditions. * @since 6.0 */ - public Version getRuntimeApiVersion() { - return sonarRuntime.getApiVersion(); + public SonarRuntime getRuntime() { + return sonarRuntime; } /** @@ -151,13 +151,6 @@ public interface Plugin { return extensions; } - /** - * Test the product the plugin is currently executed in. This can allow to implement a different behavior. - * @since 6.0 - */ - public SonarProduct getRuntimeProduct() { - return sonarRuntime.getProduct(); - } } /** diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeSide.java b/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeSide.java index 5e02c2eae61..7aa312e76a1 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeSide.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeSide.java @@ -20,13 +20,14 @@ package org.sonar.api; /** - * Differentiate runtime context in SonarQube product. + * Runtime stack in SonarQube product. + * @see SonarRuntime#getSonarQubeSide() * @since 6.0 */ public enum SonarQubeSide { SCANNER, SERVER, - COMPUTE_ENGINE; + COMPUTE_ENGINE } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java b/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java index 044df52a450..6b4e100939f 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java @@ -19,118 +19,48 @@ */ package org.sonar.api; -import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import org.sonar.api.batch.ScannerSide; -import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.server.ServerSide; import org.sonar.api.utils.Version; +import static java.util.Objects.requireNonNull; + /** - * Version of SonarQube at runtime. This component can be injected as a dependency - * of plugin extensions. The main usage for a plugin is to benefit from new APIs - * while keeping backward-compatibility with previous versions of SonarQube. - * <br><br> - * - * Example 1: a {@link Sensor} wants to use an API introduced in version 5.5 and still requires to support older versions - * at runtime. - * <pre> - * public class MySensor implements Sensor { - * - * public void execute(SensorContext context) { - * if (context.getSonarQubeVersion().isGreaterThanOrEqual(SonarQubeVersion.V5_5)) { - * context.newMethodIntroducedIn5_5(); - * } - * } - * } - * </pre> - * - * Example 2: a plugin needs to use an API introduced in version 5.6 ({@code AnApi} in the following - * snippet) and still requires to support version 5.5 at runtime. - * <br> - * <pre> - * // Component provided by sonar-plugin-api - * // @since 5.5 - * public interface AnApi { - * // implicitly since 5.5 - * public void foo(); - * - * // @since 5.6 - * public void bar(); - * } - * - * // Component provided by plugin - * public class MyExtension { - * private final SonarQubeVersion sonarQubeVersion; - * private final AnApi api; - * - * public MyExtension(SonarQubeVersion sonarQubeVersion, AnApi api) { - * this.sonarQubeVersion = sonarQubeVersion; - * this.api = api; - * } - * - * public void doSomething() { - * // assume that runtime is 5.5+ - * api.foo(); - * - * if (sonarQubeVersion.isGreaterThanOrEqual(SonarQubeVersion.V5_6)) { - * api.bar(); - * } - * } - * } - * </pre> - * <p> - * The minimal supported version of SonarQube is verified at runtime. As plugin is built - * with sonar-plugin-api 5.6, we assume that the plugin requires v5.6 or greater at runtime. - * For this reason the plugin must default which is the minimal supported version - * in the configuration of sonar-packaging-maven-plugin 1.16+: - * <p> - * <pre> - * <packaging>sonar-plugin</packaging> - * - * <dependencies> - * <dependency> - * <groupId>org.sonarsource.sonarqube</groupId> - * <artifactId>sonar-plugin-api</artifactId> - * <version>5.6</version> - * <scope>provided</scope> - * </dependency> - * </dependencies> - * - * <build> - * <plugins> - * <plugin> - * <groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId> - * <artifactId>sonar-packaging-maven-plugin</artifactId> - * <version>1.16</version> - * <extensions>true</extensions> - * <configuration> - * <!-- Override the default value 5.6 which is guessed from sonar-plugin-api dependency --> - * <sonarQubeMinVersion>5.5</sonarQubeMinVersion> - * </configuration> - * </plugin> - * </plugins> - * </build> - * </pre> - * + * Version of SonarQube at runtime. Replaced by {@link SonarRuntime#getApiVersion()}. * * @since 5.5 - * @deprecated since 6.0 replaced by {@link SonarRuntime} + * @deprecated replaced by {@link SonarRuntime} in version 6.0 */ @ScannerSide @ServerSide @ComputeEngineSide @Immutable @Deprecated -public class SonarQubeVersion extends SonarRuntime { +public class SonarQubeVersion { + /** + * Constant for version 5.5 + */ + public static final Version V5_5 = Version.create(5, 5); - public SonarQubeVersion(Version version, SonarProduct product, @Nullable SonarQubeSide sonarQubeSide) { - super(version, product, sonarQubeSide); + /** + * Constant for version 5.6 + */ + public static final Version V5_6 = Version.create(5, 6); + + private final Version version; + + public SonarQubeVersion(Version version) { + requireNonNull(version); + this.version = version; } public Version get() { - return super.getApiVersion(); + return this.version; } + public boolean isGreaterThanOrEqual(Version than) { + return this.version.isGreaterThanOrEqual(than); + } } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/SonarRuntime.java b/sonar-plugin-api/src/main/java/org/sonar/api/SonarRuntime.java index 86b37e9e54c..b2663ca1da8 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/SonarRuntime.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/SonarRuntime.java @@ -19,75 +19,81 @@ */ package org.sonar.api; -import com.google.common.base.Preconditions; -import javax.annotation.Nullable; -import javax.annotation.concurrent.Immutable; import org.sonar.api.batch.ScannerSide; import org.sonar.api.batch.sensor.Sensor; +import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.server.ServerSide; import org.sonar.api.utils.Version; import org.sonarsource.api.sonarlint.SonarLintSide; -import static java.util.Objects.requireNonNull; - /** - * Version of SonarQube at runtime. This component can be injected as a dependency - * of plugin extensions. The main usage for a plugin is to benefit from new APIs - * while keeping backward-compatibility with previous versions of SonarQube. - * <br><br> - * - * Example 1: a {@link Sensor} wants to use an API introduced in version 5.5 and still requires to support older versions - * at runtime. - * <pre> - * public class MySensor implements Sensor { + * Information about runtime environment. * - * public void execute(SensorContext context) { - * if (context.getRuntimeApiVersion().isGreaterThanOrEqual(RuntimeApiVersion.V5_5)) { - * context.newMethodIntroducedIn5_5(); - * } - * } - * } - * </pre> + * <p> + * A usage for plugins is to benefit from new APIs + * while keeping backward-compatibility with previous versions of SonarQube + * or SonarLint. + * </p> * - * Example 2: a plugin needs to use an API introduced in version 5.6 ({@code AnApi} in the following - * snippet) and still requires to support version 5.5 at runtime. - * <br> + * <p> + * Example: a plugin extension wants to use a new feature of API 6.0 without + * breaking compatibility with version 5.6 at runtime. This new feature + * would be enabled only in 6.0 and greater runtimes. + * </p> * <pre> * // Component provided by sonar-plugin-api - * // @since 5.5 + * // @since 5.6 * public interface AnApi { - * // implicitly since 5.5 + * // implicitly since 5.6 * public void foo(); * - * // @since 5.6 + * // @since 6.0 * public void bar(); * } * - * // Component provided by plugin + * // Plugin extension * public class MyExtension { - * private final RuntimeApiVersion runtimeApiVersion; + * private final SonarRuntime sonarRuntime; * private final AnApi api; * - * public MyExtension(RuntimeApiVersion runtimeApiVersion, AnApi api) { - * this.runtimeApiVersion = runtimeApiVersion; + * public MyExtension(SonarRuntime sonarRuntime, AnApi api) { + * this.sonarRuntime = sonarRuntime; * this.api = api; * } * * public void doSomething() { - * // assume that runtime is 5.5+ + * // assume that minimal supported runtime is 5.6 * api.foo(); * - * if (runtimeApiVersion.isGreaterThanOrEqual(SonarQubeVersion.V5_6)) { + * if (sonarRuntime.getApiVersion().isGreaterThanOrEqual(Version.create(6, 0))) { * api.bar(); * } * } * } * </pre> + * + * + * <p> + * Note that {@link Sensor} extensions can directly get {@link SonarRuntime} through + * {@link SensorContext#runtime()}, without using constructor injection: + * </p> + * <pre> + * public class MySensor implements Sensor { + * + * public void execute(SensorContext context) { + * if (context.runtime().getApiVersion().isGreaterThanOrEqual(Version.create(6, 0)) { + * context.newMethodIntroducedIn6_0(); + * } + * } + * + * } + * </pre> + * * <p> * The minimal supported version of plugin API is verified at runtime. As plugin is built - * with sonar-plugin-api 5.6, we assume that the plugin requires v5.6 or greater at runtime. - * For this reason the plugin must default which is the minimal supported version + * with sonar-plugin-api 6.0, we assume that the plugin requires v6.0 or greater at runtime. + * For this reason the plugin must override the minimal supported version * in the configuration of sonar-packaging-maven-plugin 1.16+: * <p> * <pre> @@ -97,7 +103,7 @@ import static java.util.Objects.requireNonNull; * <dependency> * <groupId>org.sonarsource.sonarqube</groupId> * <artifactId>sonar-plugin-api</artifactId> - * <version>5.6</version> + * <version>6.0</version> * <scope>provided</scope> * </dependency> * </dependencies> @@ -111,80 +117,42 @@ import static java.util.Objects.requireNonNull; * <extensions>true</extensions> * <configuration> * <!-- Override the default value 5.6 which is guessed from sonar-plugin-api dependency --> - * <sonarQubeMinVersion>5.5</sonarQubeMinVersion> + * <sonarQubeMinVersion>5.6</sonarQubeMinVersion> * </configuration> * </plugin> * </plugins> * </build> * </pre> * - * + * <p> + * Unit tests of plugin extensions can create instances of {@link SonarRuntime} + * via {@link org.sonar.api.internal.SonarRuntimeImpl}. + * </p> * @since 6.0 */ @ScannerSide @ServerSide @ComputeEngineSide @SonarLintSide -@Immutable -public class SonarRuntime { +public interface SonarRuntime { /** - * Constant for version 5.5 - */ - public static final Version V5_5 = Version.create(5, 5); - - /** - * Constant for version 5.6 - */ - public static final Version V5_6 = Version.create(5, 6); - - /** - * Constant for version 6.0 - */ - public static final Version V6_0 = Version.create(6, 0); - - private final Version version; - private final SonarProduct product; - private final SonarQubeSide sonarQubeSide; - - public SonarRuntime(Version version, SonarProduct product, @Nullable SonarQubeSide sonarQubeSide) { - requireNonNull(version); - requireNonNull(product); - Preconditions.checkArgument((product == SonarProduct.SONARQUBE) == (sonarQubeSide != null), "sonarQubeSide should be provided only for SonarQube product"); - this.version = version; - this.product = product; - this.sonarQubeSide = sonarQubeSide; - } - - /** - * Runtime version of sonar-plugin-api. This could be used to test if a new feature can be used or not without using reflection. - */ - public Version getApiVersion() { - return this.version; - } - - public boolean isGreaterThanOrEqual(Version than) { - return this.version.isGreaterThanOrEqual(than); - } + * Version of API (sonar-plugin-api artifact) at runtime. + * It can be helpful to call some API classes/methods without checking their availability at + * runtime by using reflection. + */ + Version getApiVersion(); /** - * Allow to know what is current runtime product. Can be used to implement different behavior depending on runtime (SonarQube, SonarLint, ...). - * @since 6.0 + * The product being executed at runtime. It targets analysers so that they can implement + * different behaviours in SonarQube and SonarLint. */ - public SonarProduct getProduct() { - return product; - } + SonarProduct getProduct(); /** - * Allow to know the precise runtime context in SonarQube product. Only valid when {@link #getProduct()} returns {@link SonarProduct#SONARQUBE} - * @since 6.0 - * @throws UnsupportedOperationException if called and {@link #getProduct()} is not equal to {@link SonarProduct#SONARQUBE} + * The SonarQube stack being executed at runtime. + * @throws UnsupportedOperationException if {@link #getProduct()} is not equal to {@link SonarProduct#SONARQUBE} */ - public SonarQubeSide getSonarQubeSide() { - if (sonarQubeSide == null) { - throw new UnsupportedOperationException("Can only be called in SonarQube"); - } - return sonarQubeSide; - } + SonarQubeSide getSonarQubeSide(); } 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 9612521b23f..c92ab74a5d9 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 @@ -20,7 +20,7 @@ package org.sonar.api.batch.sensor; import java.io.Serializable; -import org.sonar.api.SonarProduct; +import org.sonar.api.SonarRuntime; import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.rule.ActiveRules; @@ -66,25 +66,24 @@ public interface SensorContext { /** * @since 5.5 - * @deprecated since 6.0 replaced by {@link #getRuntimeApiVersion()} + * @deprecated replaced by {@link #runtime()}.getApiVersion() in version 6.0. */ @Deprecated Version getSonarQubeVersion(); /** + * Runtime information, mainly: + * <ul> + * <li>to be able to have different behaviours between SonarQube and SonarLint</li> + * <li>to enable new features depending on version of API available at runtime</li> + * </ul> * @since 6.0 */ - Version getRuntimeApiVersion(); - - /** - * Test the product the plugin is currently executed in. This can allow to implement a different behavior. - * @since 6.0 - */ - SonarProduct getRuntimeProduct(); + SonarRuntime runtime(); /** * Test if a cancellation of the analysis was requested. Sensors should periodically test this flag - * and gracefully stop if value is true. For example it could be tested between each processed file. + * and gracefully stop if value is {@code true}. For example it could be tested between each processed file. * @since 6.0 */ boolean isCancelled(); @@ -139,7 +138,7 @@ public interface SensorContext { /** * Builder to declare errors that happened while processing a source file. - * Don't forget to call {@link NewAnalisisError#save()}. + * Don't forget to call {@link NewAnalysisError#save()}. * @since 6.0 */ NewAnalysisError newAnalysisError(); 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 a2c8cd2ac26..ba9020829a4 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 @@ -19,7 +19,6 @@ */ package org.sonar.api.batch.sensor.internal; -import com.google.common.annotations.Beta; import java.io.File; import java.io.Serializable; import java.nio.file.Path; @@ -30,9 +29,8 @@ import java.util.List; import java.util.Map; import java.util.Set; import javax.annotation.CheckForNull; -import org.sonar.api.SonarProduct; import org.sonar.api.SonarQubeSide; -import org.sonar.api.SonarQubeVersion; +import org.sonar.api.SonarRuntime; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.fs.TextRange; import org.sonar.api.batch.fs.internal.DefaultFileSystem; @@ -63,7 +61,8 @@ 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.Settings; -import org.sonar.api.internal.SonarRuntimeFactory; +import org.sonar.api.internal.ApiVersion; +import org.sonar.api.internal.SonarRuntimeImpl; import org.sonar.api.measures.Metric; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; @@ -84,7 +83,6 @@ import org.sonar.duplications.internal.pmd.TokensLine; * Then pass it to your {@link Sensor}. You can then query elements provided by your sensor using methods {@link #allIssues()}, ... * */ -@Beta public class SensorContextTester implements SensorContext { private Settings settings; @@ -92,7 +90,7 @@ public class SensorContextTester implements SensorContext { private ActiveRules activeRules; private InMemorySensorStorage sensorStorage; private InputModule module; - private SonarQubeVersion sqVersion; + private SonarRuntime runtime; private boolean cancelled; private SensorContextTester(Path moduleBaseDir) { @@ -101,7 +99,7 @@ public class SensorContextTester implements SensorContext { this.activeRules = new ActiveRulesBuilder().build(); this.sensorStorage = new InMemorySensorStorage(); this.module = new DefaultInputModule("projectKey"); - this.sqVersion = SonarRuntimeFactory.create(System2.INSTANCE, SonarProduct.SONARQUBE, SonarQubeSide.SCANNER); + this.runtime = SonarRuntimeImpl.forSonarQube(ApiVersion.load(System2.INSTANCE), SonarQubeSide.SCANNER); } public static SensorContextTester create(File moduleBaseDir) { @@ -143,26 +141,25 @@ public class SensorContextTester implements SensorContext { } /** - * Default value is the version of this API. You can override it - * using {@link #setSonarQubeVersion(Version)} to test your Sensor behavior. + * Default value is the version of this API at compilation time. You can override it + * using {@link #setRuntime(SonarRuntime)} to test your Sensor behaviour. */ @Override public Version getSonarQubeVersion() { - return sqVersion.getApiVersion(); - } - - @Override - public Version getRuntimeApiVersion() { - return sqVersion.getApiVersion(); + return runtime().getApiVersion(); } + /** + * @see #setRuntime(SonarRuntime) to override defaults (SonarQube scanner with version + * of this API as used at compilation time). + */ @Override - public SonarProduct getRuntimeProduct() { - return sqVersion.getProduct(); + public SonarRuntime runtime() { + return runtime; } - public SensorContextTester setRuntime(Version version, SonarProduct product, SonarQubeSide sonarQubeSide) { - this.sqVersion = new SonarQubeVersion(version, product, sonarQubeSide); + public SensorContextTester setRuntime(SonarRuntime runtime) { + this.runtime = runtime; return this; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeFactory.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/ApiVersion.java index b47189b58a8..de57cf0761a 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeFactory.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/internal/ApiVersion.java @@ -23,29 +23,27 @@ import com.google.common.io.Resources; import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; -import javax.annotation.Nullable; -import org.sonar.api.SonarProduct; -import org.sonar.api.SonarQubeSide; -import org.sonar.api.SonarQubeVersion; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; /** - * For internal use only. + * For internal use + * + * @since 6.0 */ -public class SonarRuntimeFactory { +public class ApiVersion { private static final String FILE_PATH = "/sq-version.txt"; - private SonarRuntimeFactory() { - // prevents instantiation + private ApiVersion() { + // only static methods } - public static SonarQubeVersion create(System2 system, SonarProduct product, @Nullable SonarQubeSide sonarQubeSide) { + public static Version load(System2 system) { try { URL url = system.getResource(FILE_PATH); String versionInFile = Resources.toString(url, StandardCharsets.UTF_8); - return new SonarQubeVersion(Version.parse(versionInFile), product, sonarQubeSide); + return Version.parse(versionInFile); } catch (IOException e) { throw new IllegalStateException("Can not load " + FILE_PATH + " from classpath", e); } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java new file mode 100644 index 00000000000..601c8d017c2 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java @@ -0,0 +1,83 @@ +/* + * 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.api.internal; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; +import org.sonar.api.SonarProduct; +import org.sonar.api.SonarQubeSide; +import org.sonar.api.SonarRuntime; +import org.sonar.api.utils.Version; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.util.Objects.requireNonNull; + +/** + * @since 6.0 + */ +@Immutable +public class SonarRuntimeImpl implements SonarRuntime { + + private final Version version; + private final SonarProduct product; + private final SonarQubeSide sonarQubeSide; + + private SonarRuntimeImpl(Version version, SonarProduct product, @Nullable SonarQubeSide sonarQubeSide) { + requireNonNull(version); + requireNonNull(product); + checkArgument((product == SonarProduct.SONARQUBE) == (sonarQubeSide != null), "sonarQubeSide should be provided only for SonarQube product"); + this.version = version; + this.product = product; + this.sonarQubeSide = sonarQubeSide; + } + + @Override + public Version getApiVersion() { + return this.version; + } + + @Override + public SonarProduct getProduct() { + return product; + } + + @Override + public SonarQubeSide getSonarQubeSide() { + if (sonarQubeSide == null) { + throw new UnsupportedOperationException("Can only be called in SonarQube"); + } + return sonarQubeSide; + } + + /** + * Create an instance for SonarQube runtime environment. + */ + public static SonarRuntime forSonarQube(Version version, SonarQubeSide side) { + return new SonarRuntimeImpl(version, SonarProduct.SONARQUBE, side); + } + + /** + * Create an instance for SonarLint runtime environment. + */ + public static SonarRuntime forSonarLint(Version version) { + return new SonarRuntimeImpl(version, SonarProduct.SONARLINT, null); + } + +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java b/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java index 8d52dce62d5..f8aa4bd2a2c 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/platform/Server.java @@ -27,24 +27,62 @@ import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.server.ServerSide; /** + * Runtime information about server + * * @since 2.2 - */ + */ @ScannerSide @ServerSide @ComputeEngineSide public abstract class Server { + /** + * Name is misleading, this is an UUID generated + * at each startup, so it changes if server is restarted. + * @return a non-null UUID. Format can change over versions. + */ public abstract String getId(); + /** + * UUID generated on demand by system administrators. It is + * {@code null} by default on fresh installations. When defined, + * value does not change when server is restarted. + * @since 2.10 + */ + @CheckForNull + public abstract String getPermanentServerId(); + + /** + * Non-null version of SonarQube at runtime + */ public abstract String getVersion(); + /** + * Date when server started + */ public abstract Date getStartedAt(); + /** + * @deprecated in 6.0. Replaced by {@link ServerFileSystem#getHomeDir()} + * @return an existing directory in server and CE environments, {@code null} in scanner. + */ + @Deprecated public abstract File getRootDir(); + /** + * @deprecated always {@code null} since version 6.0. No alternatives, as plugins do not have to touch this directory. + */ + @Deprecated @CheckForNull public abstract File getDeployDir(); + /** + * Context path of web server. Value is blank {@code ""} by default. When defined by + * the property {@code sonar.web.context} of conf/sonar.properties, then value starts but does + * not end with slash {@code '/'}, for instance {@code "/sonarqube"}. + * + * @return non-null but possibly blank path + */ public abstract String getContextPath(); /** @@ -56,7 +94,7 @@ public abstract class Server { public abstract String getPublicRootUrl(); /** - * The dev mode is enabled when the property sonar.web.dev is true. + * The dev mode is enabled when the property {@code sonar.web.dev} is {@code true}. * * @since 5.4 */ @@ -76,9 +114,4 @@ public abstract class Server { * @since since 2.4 on batch side only, since 5.6 on both batch side and server side (WebServer and Compute Engine) */ public abstract String getURL(); - - /** - * @since 2.10 - */ - public abstract String getPermanentServerId(); } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/PluginTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/PluginTest.java index caa022c0290..2ef2d212e59 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/PluginTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/PluginTest.java @@ -21,17 +21,21 @@ package org.sonar.api; import java.util.Arrays; import org.junit.Test; +import org.sonar.api.internal.SonarRuntimeImpl; +import org.sonar.api.utils.Version; import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.api.SonarRuntime.V5_5; public class PluginTest { + private static final Version VERSION_5_6 = Version.create(5, 6); + @Test public void test_context() { - Plugin.Context context = new Plugin.Context(new SonarRuntime(V5_5, SonarProduct.SONARQUBE, SonarQubeSide.SERVER)); + SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(VERSION_5_6, SonarQubeSide.SERVER); + Plugin.Context context = new Plugin.Context(runtime); - assertThat(context.getSonarQubeVersion()).isEqualTo(V5_5); + assertThat(context.getSonarQubeVersion()).isEqualTo(VERSION_5_6); assertThat(context.getExtensions()).isEmpty(); context.addExtension("foo"); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java index 8ee63aa98fd..ac430ad82f5 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java @@ -19,22 +19,17 @@ */ package org.sonar.api; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.sonar.api.utils.Version; import static org.assertj.core.api.Assertions.assertThat; public class SonarQubeVersionTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Test public void isGte() { Version version = Version.parse("1.2.3"); - SonarQubeVersion qubeVersion = new SonarQubeVersion(version, SonarProduct.SONARLINT, null); + SonarQubeVersion qubeVersion = new SonarQubeVersion(version); assertThat(qubeVersion.get()).isEqualTo(version); assertThat(qubeVersion.isGreaterThanOrEqual(version)).isTrue(); assertThat(qubeVersion.isGreaterThanOrEqual(Version.parse("1.1"))).isTrue(); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeFactoryTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/internal/ApiVersionTest.java index 4db26447ca5..996b0648ddf 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeFactoryTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/internal/ApiVersionTest.java @@ -23,26 +23,24 @@ import java.io.File; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import org.sonar.api.SonarProduct; -import org.sonar.api.SonarQubeVersion; import org.sonar.api.utils.System2; +import org.sonar.api.utils.Version; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; -public class SonarRuntimeFactoryTest { +public class ApiVersionTest { @Rule public ExpectedException expectedException = ExpectedException.none(); @Test - public void create() { - SonarQubeVersion version = SonarRuntimeFactory.create(System2.INSTANCE, SonarProduct.SONARLINT, null); + public void load_version_from_file_in_classpath() { + Version version = ApiVersion.load(System2.INSTANCE); assertThat(version).isNotNull(); - assertThat(version.getApiVersion().major()).isGreaterThanOrEqualTo(5); - assertThat(version.getProduct()).isEqualTo(SonarProduct.SONARLINT); + assertThat(version.major()).isGreaterThanOrEqualTo(5); } @Test @@ -52,7 +50,7 @@ public class SonarRuntimeFactoryTest { System2 system = spy(System2.class); when(system.getResource(anyString())).thenReturn(new File("target/unknown").toURI().toURL()); - SonarRuntimeFactory.create(system, SonarProduct.SONARLINT, null); + ApiVersion.load(system); } } diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/SonarRuntimeTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java index 6d26a5678ce..ea214d5bef1 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/SonarRuntimeTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/internal/SonarRuntimeImplTest.java @@ -17,42 +17,40 @@ * 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; +package org.sonar.api.internal; import org.assertj.core.api.Assertions; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.sonar.api.SonarProduct; +import org.sonar.api.SonarQubeSide; +import org.sonar.api.SonarRuntime; import org.sonar.api.utils.Version; import static org.assertj.core.api.Assertions.assertThat; -public class SonarRuntimeTest { + +public class SonarRuntimeImplTest { + + private static final Version A_VERSION = Version.parse("6.0"); @Rule public ExpectedException expectedException = ExpectedException.none(); @Test - public void isGteInSQ() { - Version version = Version.parse("1.2.3"); - SonarRuntime apiVersion = new SonarRuntime(version, SonarProduct.SONARQUBE, SonarQubeSide.SCANNER); - assertThat(apiVersion.getApiVersion()).isEqualTo(version); + public void sonarQube_environment() { + SonarRuntime apiVersion = SonarRuntimeImpl.forSonarQube(A_VERSION, SonarQubeSide.SCANNER); + assertThat(apiVersion.getApiVersion()).isEqualTo(A_VERSION); assertThat(apiVersion.getProduct()).isEqualTo(SonarProduct.SONARQUBE); assertThat(apiVersion.getSonarQubeSide()).isEqualTo(SonarQubeSide.SCANNER); - assertThat(apiVersion.isGreaterThanOrEqual(version)).isTrue(); - assertThat(apiVersion.isGreaterThanOrEqual(Version.parse("1.1"))).isTrue(); - assertThat(apiVersion.isGreaterThanOrEqual(Version.parse("1.3"))).isFalse(); } @Test - public void inSL() { - Version version = Version.parse("1.2.3"); - SonarRuntime apiVersion = new SonarRuntime(version, SonarProduct.SONARLINT, null); - assertThat(apiVersion.getApiVersion()).isEqualTo(version); + public void sonarLint_environment() { + SonarRuntime apiVersion = SonarRuntimeImpl.forSonarLint(A_VERSION); + assertThat(apiVersion.getApiVersion()).isEqualTo(A_VERSION); assertThat(apiVersion.getProduct()).isEqualTo(SonarProduct.SONARLINT); - assertThat(apiVersion.isGreaterThanOrEqual(version)).isTrue(); - assertThat(apiVersion.isGreaterThanOrEqual(Version.parse("1.1"))).isTrue(); - assertThat(apiVersion.isGreaterThanOrEqual(Version.parse("1.3"))).isFalse(); try { apiVersion.getSonarQubeSide(); Assertions.fail("Expected exception"); @@ -62,12 +60,10 @@ public class SonarRuntimeTest { } @Test(expected = IllegalArgumentException.class) - public void testConstructorMissSide() throws Exception { - new SonarRuntime(Version.parse("1.2.3"), SonarProduct.SONARQUBE, null); + public void sonarqube_requires_side() throws Exception { + SonarRuntimeImpl.forSonarQube(A_VERSION, null); } - @Test(expected = IllegalArgumentException.class) - public void testConstructorNoSideOnSonarLint() throws Exception { - new SonarRuntime(Version.parse("1.2.3"), SonarProduct.SONARLINT, SonarQubeSide.COMPUTE_ENGINE); - } + + } |