]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7458 new component org.sonar.api.utils.Version
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 15 Mar 2016 09:14:26 +0000 (10:14 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Wed, 16 Mar 2016 18:42:59 +0000 (19:42 +0100)
sonar-db/src/main/java/org/sonar/db/DatabaseChecker.java
sonar-plugin-api/src/main/java/org/sonar/api/utils/Version.java [new file with mode: 0644]
sonar-plugin-api/src/test/java/org/sonar/api/utils/VersionTest.java [new file with mode: 0644]

index eb436a8a1551eb98f3598233b38a7c0d597a5ee5..d4ce26de57378d959167dbf34021e1f1fc046882 100644 (file)
@@ -27,6 +27,7 @@ import java.util.Map;
 import org.apache.commons.lang.StringUtils;
 import org.picocontainer.Startable;
 import org.sonar.api.utils.MessageException;
+import org.sonar.api.utils.Version;
 import org.sonar.api.utils.log.Loggers;
 import org.sonar.db.dialect.H2;
 import org.sonar.db.dialect.MsSql;
@@ -44,10 +45,10 @@ public class DatabaseChecker implements Startable {
     // MsSQL 2012 is 11.x
     // MsSQL 2014 is 12.x
     // https://support.microsoft.com/en-us/kb/321185
-    MsSql.ID, new Version(10, 0),
-    MySql.ID, new Version(5, 6),
-    Oracle.ID, new Version(11, 0),
-    PostgreSql.ID, new Version(8, 0));
+    MsSql.ID, Version.create(10, 0, 0),
+    MySql.ID, Version.create(5, 6, 0),
+    Oracle.ID, Version.create(11, 0, 0),
+    PostgreSql.ID, Version.create(8, 0, 0));
 
   private final Database db;
 
@@ -82,8 +83,8 @@ public class DatabaseChecker implements Startable {
       try (Connection connection = db.getDataSource().getConnection()) {
         int dbMajorVersion = connection.getMetaData().getDatabaseMajorVersion();
         int dbMinorVersion = connection.getMetaData().getDatabaseMinorVersion();
-        Version dbVersion = new Version(dbMajorVersion, dbMinorVersion);
-        if (!dbVersion.isGreaterThanOrEqual(minDbVersion)) {
+        Version dbVersion = Version.create(dbMajorVersion, dbMinorVersion, 0);
+        if (dbVersion.compareTo(minDbVersion) < 0) {
           throw MessageException.of(String.format(
             "Unsupported %s version: %s. Minimal supported version is %s.", db.getDialect().getId(), dbVersion, minDbVersion));
         }
@@ -102,23 +103,4 @@ public class DatabaseChecker implements Startable {
       }
     }
   }
-
-  private static class Version {
-    private final int major;
-    private final int minor;
-
-    public Version(int major, int minor) {
-      this.major = major;
-      this.minor = minor;
-    }
-
-    public boolean isGreaterThanOrEqual(Version other) {
-      return major >= other.major && (major != other.major || minor >= other.minor);
-    }
-
-    @Override
-    public String toString() {
-      return new StringBuilder().append(major).append(".").append(minor).toString();
-    }
-  }
 }
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
new file mode 100644 (file)
index 0000000..d1dc9b5
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * 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.utils;
+
+import com.google.common.base.Splitter;
+import java.util.List;
+import javax.annotation.concurrent.Immutable;
+
+import static java.lang.Integer.parseInt;
+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
+ * @since 5.5
+ */
+@Immutable
+public class Version implements Comparable<Version> {
+
+  private static final String QUALIFIER_SEPARATOR = "-";
+  private static final char SEQUENCE_SEPARATOR = '.';
+  private static final Splitter SEQUENCE_SPLITTER = Splitter.on(SEQUENCE_SEPARATOR);
+
+  private final int major;
+  private final int minor;
+  private final int patch;
+  private final String qualifier;
+
+  private Version(int major, int minor, int patch, String qualifier) {
+    this.major = major;
+    this.minor = minor;
+    this.patch = patch;
+    this.qualifier = qualifier;
+  }
+
+  public int major() {
+    return major;
+  }
+
+  public int minor() {
+    return minor;
+  }
+
+  public int patch() {
+    return patch;
+  }
+
+  /**
+   * @return non-null suffix
+   */
+  public String qualifier() {
+    return qualifier;
+  }
+
+  public static Version parse(String text) {
+    String s = trimToEmpty(text);
+    String qualifier = substringAfter(s, QUALIFIER_SEPARATOR);
+    if (!qualifier.isEmpty()) {
+      s = substringBefore(s, QUALIFIER_SEPARATOR);
+    }
+    List<String> split = SEQUENCE_SPLITTER.splitToList(s);
+    int major = 0;
+    int minor = 0;
+    int patch = 0;
+    if (split.size() > 0) {
+      major = parseSequence(split.get(0));
+      if (split.size() > 1) {
+        minor = parseSequence(split.get(1));
+        if (split.size() > 2) {
+          patch = parseSequence(split.get(2));
+          if (split.size() > 3) {
+            throw new IllegalArgumentException("Only 3 sequences are accepted");
+          }
+        }
+      }
+    }
+    return new Version(major, minor, patch, qualifier);
+  }
+
+  public static Version create(int major, int minor) {
+    return new Version(major, minor, 0, "");
+  }
+
+  public static Version create(int major, int minor, int patch) {
+    return new Version(major, minor, patch, "");
+  }
+
+  public static Version create(int major, int minor, int patch, String qualifier) {
+    return new Version(major, minor, patch, qualifier);
+  }
+
+  private static int parseSequence(String sequence) {
+    if (sequence.isEmpty()) {
+      return 0;
+    }
+    return parseInt(sequence);
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof Version)) {
+      return false;
+    }
+    Version other = (Version) o;
+    return major == other.major && minor == other.minor && patch == other.patch;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = major;
+    result = 31 * result + minor;
+    result = 31 * result + patch;
+    return result;
+  }
+
+  @Override
+  public int compareTo(Version other) {
+    int c = major - other.major;
+    if (c == 0) {
+      c = minor - other.minor;
+      if (c == 0) {
+        c = patch - other.patch;
+      }
+    }
+    return c;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append(major).append(SEQUENCE_SEPARATOR).append(minor);
+    if (patch > 0) {
+      sb.append(SEQUENCE_SEPARATOR).append(patch);
+    }
+    if (!qualifier.isEmpty()) {
+      sb.append(QUALIFIER_SEPARATOR).append(qualifier);
+    }
+    return sb.toString();
+  }
+}
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
new file mode 100644 (file)
index 0000000..ed76506
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * 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.utils;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.utils.Version.parse;
+
+public class VersionTest {
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  public void test_parse() {
+    assertVersion(parse(""), 0, 0, 0, "");
+    assertVersion(parse("1"), 1, 0, 0, "");
+    assertVersion(parse("1.2"), 1, 2, 0, "");
+    assertVersion(parse("1.2.3"), 1, 2, 3, "");
+    assertVersion(parse("1.2-beta-1"), 1, 2, 0, "beta-1");
+    assertVersion(parse("1.2.3-beta1"), 1, 2, 3, "beta1");
+    assertVersion(parse("1.2.3-beta-1"), 1, 2, 3, "beta-1");
+  }
+
+  @Test
+  public void parse_throws_IAE_if_more_than_3_sequences() {
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Only 3 sequences are accepted");
+    parse("1.2.3.4");
+  }
+
+  @Test
+  public void test_equals() {
+    Version one = parse("1");
+    assertThat(one).isEqualTo(one);
+    assertThat(one).isEqualTo(parse("1"));
+    assertThat(one).isEqualTo(parse("1.0"));
+    assertThat(one).isEqualTo(parse("1.0.0"));
+    assertThat(one).isNotEqualTo(parse("1.2.3"));
+
+    assertThat(parse("1.2.3")).isEqualTo(parse("1.2.3"));
+    assertThat(parse("1.2.3")).isNotEqualTo(parse("1.2.4"));
+    assertThat(parse("1.2.3")).isEqualTo(parse("1.2.3-b1"));
+    assertThat(parse("1.2.3-b1")).isEqualTo(parse("1.2.3-b2"));
+  }
+
+  @Test
+  public void test_hashCode() {
+    assertThat(parse("1").hashCode()).isEqualTo(parse("1").hashCode());
+    assertThat(parse("1").hashCode()).isEqualTo(parse("1.0.0").hashCode());
+    assertThat(parse("1.2.3-beta1").hashCode()).isEqualTo(parse("1.2.3").hashCode());
+  }
+
+  @Test
+  public void test_compareTo() {
+    assertThat(parse("1.2").compareTo(parse("1.2.0"))).isEqualTo(0);
+    assertThat(parse("1.2.3").compareTo(parse("1.2.3"))).isEqualTo(0);
+    assertThat(parse("1.2.3").compareTo(parse("1.2.4"))).isLessThan(0);
+    assertThat(parse("1.2.3").compareTo(parse("1.3"))).isLessThan(0);
+    assertThat(parse("1.2.3").compareTo(parse("2.1"))).isLessThan(0);
+    assertThat(parse("1.2.3").compareTo(parse("2.0.0"))).isLessThan(0);
+    assertThat(parse("2.0").compareTo(parse("1.2"))).isGreaterThan(0);
+  }
+
+  @Test
+  public void qualifier_is_ignored_from_comparison() {
+    assertThat(parse("1.2.3")).isEqualTo(parse("1.2.3-build1"));
+    assertThat(parse("1.2.3")).isEqualTo(parse("1.2.3-build1"));
+    assertThat(parse("1.2.3").compareTo(parse("1.2.3-build1"))).isEqualTo(0);
+  }
+
+  @Test
+  public void test_toString() {
+    assertThat(parse("1").toString()).isEqualTo("1.0");
+    assertThat(parse("1.2").toString()).isEqualTo("1.2");
+    assertThat(parse("1.2.3").toString()).isEqualTo("1.2.3");
+    assertThat(parse("1.2-b1").toString()).isEqualTo("1.2-b1");
+    assertThat(parse("1.2.3-b1").toString()).isEqualTo("1.2.3-b1");
+  }
+
+  private static void assertVersion(Version version,
+    int expectedMajor, int expectedMinor, int expectedPatch, String expectedQualifier) {
+    assertThat(version.major()).isEqualTo(expectedMajor);
+    assertThat(version.minor()).isEqualTo(expectedMinor);
+    assertThat(version.patch()).isEqualTo(expectedPatch);
+    assertThat(version.qualifier()).isEqualTo(expectedQualifier);
+  }
+}