diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-03-15 10:14:45 +0100 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-03-16 19:42:59 +0100 |
commit | 824a1c63f89e7e611f15d007faf55f2e0d0a8558 (patch) | |
tree | cd524c642c3acfcd7a06e70c0c7f555a68de50d5 | |
parent | 13f9918a47199fdbd35261e49e6d15b5c8bfdc36 (diff) | |
download | sonarqube-824a1c63f89e7e611f15d007faf55f2e0d0a8558.tar.gz sonarqube-824a1c63f89e7e611f15d007faf55f2e0d0a8558.zip |
SONAR-7458 new component org.sonar.api.SonarQubeVersion
8 files changed, 332 insertions, 3 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java index 39491d3e6b0..361e35c3558 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java @@ -24,6 +24,7 @@ import javax.annotation.Nullable; import org.sonar.api.utils.System2; import org.sonar.api.utils.internal.TempFolderCleaner; import org.sonar.core.config.CorePropertyDefinitions; +import org.sonar.core.platform.SonarQubeVersionProvider; import org.sonar.core.util.UuidFactoryImpl; import org.sonar.db.DaoModule; import org.sonar.db.DatabaseChecker; @@ -66,6 +67,7 @@ public class PlatformLevel1 extends PlatformLevel { add(platform, properties); addExtraRootComponents(); add( + new SonarQubeVersionProvider(), ServerSettings.class, ServerImpl.class, UuidFactoryImpl.INSTANCE, diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java index aa107887ea4..0a2ec661d73 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java @@ -43,6 +43,7 @@ import org.sonar.batch.task.Tasks; import org.sonar.core.component.DefaultResourceTypes; import org.sonar.core.config.CorePropertyDefinitions; import org.sonar.core.issue.tracking.Tracker; +import org.sonar.core.platform.SonarQubeVersionProvider; public class BatchComponents { private BatchComponents() { @@ -51,6 +52,7 @@ public class BatchComponents { public static Collection<Object> all(AnalysisMode analysisMode) { List<Object> components = Lists.newArrayList( + new SonarQubeVersionProvider(), DefaultResourceTypes.get(), // Tasks diff --git a/sonar-core/src/main/java/org/sonar/core/platform/SonarQubeVersionProvider.java b/sonar-core/src/main/java/org/sonar/core/platform/SonarQubeVersionProvider.java new file mode 100644 index 00000000000..a0f54de7490 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/platform/SonarQubeVersionProvider.java @@ -0,0 +1,49 @@ +/* + * 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.core.platform; + +import com.google.common.io.Resources; +import java.io.IOException; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import org.picocontainer.injectors.ProviderAdapter; +import org.sonar.api.SonarQubeVersion; +import org.sonar.api.utils.System2; +import org.sonar.api.utils.Version; + +public class SonarQubeVersionProvider extends ProviderAdapter { + + private static final String FILE_PATH = "/sq-version.txt"; + + private SonarQubeVersion version = null; + + public SonarQubeVersion provide(System2 system) { + if (version == null) { + try { + URL url = system.getResource(FILE_PATH); + String versionInFile = Resources.toString(url, StandardCharsets.UTF_8); + version = new SonarQubeVersion(Version.parse(versionInFile)); + } catch (IOException e) { + throw new IllegalStateException("Can not load " + FILE_PATH + " from classpath", e); + } + } + return version; + } +} diff --git a/sonar-core/src/test/java/org/sonar/core/platform/SonarQubeVersionProviderTest.java b/sonar-core/src/test/java/org/sonar/core/platform/SonarQubeVersionProviderTest.java new file mode 100644 index 00000000000..79d9baddc27 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/platform/SonarQubeVersionProviderTest.java @@ -0,0 +1,64 @@ +/* + * 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.core.platform; + +import java.io.File; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.SonarQubeVersion; +import org.sonar.api.utils.System2; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class SonarQubeVersionProviderTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + SonarQubeVersionProvider underTest = new SonarQubeVersionProvider(); + + @Test + public void create() { + SonarQubeVersion version = underTest.provide(System2.INSTANCE); + assertThat(version).isNotNull(); + assertThat(version.get().major()).isGreaterThanOrEqualTo(5); + } + + @Test + public void cache_version() { + SonarQubeVersion version1 = underTest.provide(System2.INSTANCE); + SonarQubeVersion version2 = underTest.provide(System2.INSTANCE); + assertThat(version1).isSameAs(version2); + } + + @Test + public void throw_ISE_if_fail_to_load_version() throws Exception { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Can not load /sq-version.txt from classpath"); + + System2 system = mock(System2.class); + when(system.getResource(anyString())).thenReturn(new File("target/unknown").toURL()); + underTest.provide(system); + } +} 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 new file mode 100644 index 00000000000..5d76568ad17 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java @@ -0,0 +1,134 @@ +/* + * 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; + +import javax.annotation.concurrent.Immutable; +import org.sonar.api.batch.BatchSide; +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. + + * Example: 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. + * <p></p> + * <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></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></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> + * + * + * @since 5.5 + */ +@BatchSide +@ServerSide +@Immutable +public class SonarQubeVersion { + + /** + * 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); + + private final Version version; + + public SonarQubeVersion(Version version) { + requireNonNull(version); + this.version = version; + } + + public Version get() { + return this.version; + } + + public boolean isGreaterThanOrEqual(Version than) { + return this.version.compareTo(than) >= 0; + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/Version.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/Version.java index d1dc9b5dbeb..f009dc61756 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/Version.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/Version.java @@ -24,12 +24,25 @@ import java.util.List; import javax.annotation.concurrent.Immutable; import static java.lang.Integer.parseInt; +import static java.util.Objects.requireNonNull; import static org.apache.commons.lang.StringUtils.substringAfter; import static org.apache.commons.lang.StringUtils.substringBefore; import static org.apache.commons.lang.StringUtils.trimToEmpty; /** - * TODO document equals/comparison without qualifier + * Version composed of 3 integer-sequences (major, minor and patch fields) and optionally a qualifier. + * <p></p> + * Examples: 1.0, 1.0.0, 1.2.3, 1.2-beta1, 1.2.1-beta-1 + * <p></p> + * <h3>IMPORTANT NOTE</h3> + * Qualifier is ignored when comparing objects (methods {@link #equals(Object)}, {@link #hashCode()} + * and {@link #compareTo(Version)}). + * <p></p> + * <pre> + * assertThat(Version.parse("1.2")).isEqualTo(Version.parse("1.2-beta1")); + * assertThat(Version.parse("1.2").compareTo(Version.parse("1.2-beta1"))).isZero(); + * </pre> + * * @since 5.5 */ @Immutable @@ -45,6 +58,7 @@ public class Version implements Comparable<Version> { private final String qualifier; private Version(int major, int minor, int patch, String qualifier) { + requireNonNull(qualifier, "Version qualifier must not be null"); this.major = major; this.minor = minor; this.patch = patch; @@ -64,12 +78,27 @@ public class Version implements Comparable<Version> { } /** - * @return non-null suffix + * @return non-null suffix. Empty if absent, else the suffix without the first character "-" */ public String qualifier() { return qualifier; } + /** + * Convert a {@link String} to a Version. Supported formats: + * <ul> + * <li>1</li> + * <li>1.2</li> + * <li>1.2.3</li> + * <li>1-beta-1</li> + * <li>1.2-beta-1</li> + * <li>1.2.3-beta-1</li> + * </ul> + * Note that the optional qualifier is the part after the first "-". + * + * @throws IllegalArgumentException if parameter is badly formatted, for example + * if it defines 4 integer-sequences. + */ public static Version parse(String text) { String s = trimToEmpty(text); String qualifier = substringAfter(s, QUALIFIER_SEPARATOR); 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 new file mode 100644 index 00000000000..0cc786c3ba4 --- /dev/null +++ b/sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java @@ -0,0 +1,38 @@ +/* + * 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; + +import org.junit.Test; +import org.sonar.api.utils.Version; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SonarQubeVersionTest { + + @Test + public void isGte() { + Version version = Version.parse("1.2.3"); + SonarQubeVersion qubeVersion = new SonarQubeVersion(version); + assertThat(qubeVersion.get()).isEqualTo(version); + assertThat(qubeVersion.isGreaterThanOrEqual(version)).isTrue(); + assertThat(qubeVersion.isGreaterThanOrEqual(Version.parse("1.1"))).isTrue(); + assertThat(qubeVersion.isGreaterThanOrEqual(Version.parse("1.3"))).isFalse(); + } +} diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/utils/VersionTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/utils/VersionTest.java index ed765062c20..a702c852fd5 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/utils/VersionTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/utils/VersionTest.java @@ -57,6 +57,7 @@ public class VersionTest { assertThat(one).isEqualTo(parse("1.0")); assertThat(one).isEqualTo(parse("1.0.0")); assertThat(one).isNotEqualTo(parse("1.2.3")); + assertThat(one).isNotEqualTo("1"); assertThat(parse("1.2.3")).isEqualTo(parse("1.2.3")); assertThat(parse("1.2.3")).isNotEqualTo(parse("1.2.4")); @@ -98,8 +99,18 @@ public class VersionTest { assertThat(parse("1.2.3-b1").toString()).isEqualTo("1.2.3-b1"); } + @Test + public void test_create() { + assertVersion(Version.create(1, 2), 1, 2, 0, ""); + assertVersion(Version.create(1, 2, 3), 1, 2, 3, ""); + assertVersion(Version.create(1, 2, 0, ""), 1, 2, 0, ""); + assertVersion(Version.create(1, 2, 3, "build1"), 1, 2, 3, "build1"); + assertThat(Version.create(1, 2, 3, "build1").toString()).isEqualTo("1.2.3-build1"); + + } + private static void assertVersion(Version version, - int expectedMajor, int expectedMinor, int expectedPatch, String expectedQualifier) { + int expectedMajor, int expectedMinor, int expectedPatch, String expectedQualifier) { assertThat(version.major()).isEqualTo(expectedMajor); assertThat(version.minor()).isEqualTo(expectedMinor); assertThat(version.patch()).isEqualTo(expectedPatch); |