aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2016-03-15 10:14:45 +0100
committerSimon Brandhof <simon.brandhof@sonarsource.com>2016-03-16 19:42:59 +0100
commit824a1c63f89e7e611f15d007faf55f2e0d0a8558 (patch)
treecd524c642c3acfcd7a06e70c0c7f555a68de50d5
parent13f9918a47199fdbd35261e49e6d15b5c8bfdc36 (diff)
downloadsonarqube-824a1c63f89e7e611f15d007faf55f2e0d0a8558.tar.gz
sonarqube-824a1c63f89e7e611f15d007faf55f2e0d0a8558.zip
SONAR-7458 new component org.sonar.api.SonarQubeVersion
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel1.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/platform/SonarQubeVersionProvider.java49
-rw-r--r--sonar-core/src/test/java/org/sonar/core/platform/SonarQubeVersionProviderTest.java64
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/SonarQubeVersion.java134
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/utils/Version.java33
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/SonarQubeVersionTest.java38
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/utils/VersionTest.java13
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>
+ * &lt;packaging&gt;sonar-plugin&lt;/packaging&gt;
+ *
+ * &lt;dependencies&gt;
+ * &lt;dependency&gt;
+ * &lt;groupId&gt;org.sonarsource.sonarqube&lt;/groupId&gt;
+ * &lt;artifactId&gt;sonar-plugin-api&lt;/artifactId&gt;
+ * &lt;version&gt;5.6&lt;/version&gt;
+ * &lt;scope&gt;provided&lt;/scope&gt;
+ * &lt;/dependency&gt;
+ * &lt;/dependencies&gt;
+ *
+ * &lt;build&gt;
+ * &lt;plugins&gt;
+ * &lt;plugin&gt;
+ * &lt;groupId&gt;org.sonarsource.sonar-packaging-maven-plugin&lt;/groupId&gt;
+ * &lt;artifactId&gt;sonar-packaging-maven-plugin&lt;/artifactId&gt;
+ * &lt;version&gt;1.16&lt;/version&gt;
+ * &lt;extensions&gt;true&lt;/extensions&gt;
+ * &lt;configuration&gt;
+ * &lt;!-- Override the default value 5.6 which is guessed from sonar-plugin-api dependency --&gt;
+ * &lt;sonarQubeMinVersion&gt;5.5&lt;/sonarQubeMinVersion&gt;
+ * &lt;/configuration&gt;
+ * &lt;/plugin&gt;
+ * &lt;/plugins&gt;
+ * &lt;/build&gt;
+ * </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);