Author: rwhitcomb
Date: Wed Apr 28 05:59:50 2021
New Revision: 1889254

URL: http://svn.apache.org/viewvc?rev=1889254&view=rev
Log:
Add "safelyDecode" into Version itself (from ApplicationContext).

Modified:
    pivot/trunk/core/src/org/apache/pivot/util/Version.java
    pivot/trunk/core/test/org/apache/pivot/util/test/VersionTest.java

Modified: pivot/trunk/core/src/org/apache/pivot/util/Version.java
URL: 
http://svn.apache.org/viewvc/pivot/trunk/core/src/org/apache/pivot/util/Version.java?rev=1889254&r1=1889253&r2=1889254&view=diff
==============================================================================
--- pivot/trunk/core/src/org/apache/pivot/util/Version.java (original)
+++ pivot/trunk/core/src/org/apache/pivot/util/Version.java Wed Apr 28 05:59:50 
2021
@@ -18,6 +18,7 @@ package org.apache.pivot.util;
 
 import java.io.Serializable;
 
+
 /**
  * Represents a version number. Version numbers are defined as: <p>
  * <i>major</i>.<i>minor</i>.<i>maintenance</i>_<i>update</i> <p> for example,
@@ -26,50 +27,102 @@ import java.io.Serializable;
 public class Version implements Comparable<Version>, Serializable {
     private static final long serialVersionUID = -3677773163272115116L;
 
-    private short majorRevision = 0;
-    private short minorRevision = 0;
-    private short maintenanceRevision = 0;
+    /**
+     * The default version object (0, 0, 0, 0).
+     */
+    public static final Version ZERO_VERSION = new Version(0, 0, 0, 0L);
+
+    /**
+     * The real major version number.
+     */
+    private short majorVersion = 0;
+    /**
+     * The real minor version number.
+     */
+    private short minorVersion = 0;
+    /**
+     * The real maintenance version number.
+     */
+    private short maintenanceVersion = 0;
+    /**
+     * The real update version number.
+     */
     private long updateRevision = 0;
+    /**
+     * The build string.
+     */
     private String build = null;
 
-    public Version(final int majorRevision, final int minorRevision, final int 
maintenanceRevision,
-        final long updateRevision) {
-        this(majorRevision, minorRevision, maintenanceRevision, 
updateRevision, null);
-    }
-
-    public Version(final int majorRevision, final int minorRevision, final int 
maintenanceRevision,
-        final long updateRevision, final String build) {
-        Utils.checkInRangeOfShort(majorRevision, "majorRevision");
-        Utils.checkInRangeOfShort(minorRevision, "minorRevision");
-        Utils.checkInRangeOfShort(maintenanceRevision, "maintenanceRevision");
-
-        this.majorRevision = (short) majorRevision;
-        this.minorRevision = (short) minorRevision;
-        this.maintenanceRevision = (short) maintenanceRevision;
-        this.updateRevision = updateRevision;
-        this.build = build;
+    /**
+     * Construct a version given all the numeric values.
+     *
+     * @param major       The new major version.
+     * @param minor       The new minor version.
+     * @param maintenance The new maintenance version.
+     * @param update      The new update version.
+     */
+    public Version(final int major, final int minor, final int maintenance, 
final long update) {
+        this(major, minor, maintenance, update, null);
+    }
+
+    /**
+     * Construct a version given all the information.
+     *
+     * @param major       The new major version.
+     * @param minor       The new minor version.
+     * @param maintenance The new maintenance version.
+     * @param update      The new update version.
+     * @param buildString The new build string.
+     */
+    public Version(final int major, final int minor, final int maintenance, 
final long update,
+            final String buildString) {
+        Utils.checkInRangeOfShort(major, "majorVersion");
+        Utils.checkInRangeOfShort(minor, "minorVersion");
+        Utils.checkInRangeOfShort(maintenance, "maintenanceVersion");
+
+        majorVersion = (short) major;
+        minorVersion = (short) minor;
+        maintenanceVersion = (short) maintenance;
+        updateRevision = update;
+        build = buildString;
     }
 
+    /**
+     * @return The major version number.
+     */
     public short getMajorRevision() {
-        return majorRevision;
+        return majorVersion;
     }
 
+    /**
+     * @return The minor version number.
+     */
     public short getMinorRevision() {
-        return minorRevision;
+        return minorVersion;
     }
 
+    /**
+     * @return The maintenance version number.
+     */
     public short getMaintenanceRevision() {
-        return maintenanceRevision;
+        return maintenanceVersion;
     }
 
+    /**
+     * @return The update revision number.
+     */
     public long getUpdateRevision() {
         return updateRevision;
     }
 
+    /**
+     * @return A composite value, consisting of all the numeric components
+     *         shifted into parts of a long.
+     */
     public long getNumber() {
-        long number = ((long) ((majorRevision) & 0xffff) << (16 * 3)
-            | (long) ((minorRevision) & 0xffff) << (16 * 2)
-            | (long) ((maintenanceRevision) & 0xffff) << (16 * 1))
+        long number = ((long) ((majorVersion) & 0xffff) << (16 * 3)
+            | (long) ((minorVersion) & 0xffff) << (16 * 2)
+            | (long) ((maintenanceVersion) & 0xffff) << (16 * 1))
             + updateRevision;
 
         return number;
@@ -92,13 +145,13 @@ public class Version implements Comparab
 
     @Override
     public String toString() {
-        String string = this.majorRevision
-            + "." + this.minorRevision
-            + "." + this.maintenanceRevision
-            + "_" + String.format("%02d", this.updateRevision);
+        String string = majorVersion
+            + "." + minorVersion
+            + "." + maintenanceVersion
+            + "_" + String.format("%02d", updateRevision);
 
-        if (this.build != null) {
-            string += "-" + this.build;
+        if (build != null) {
+            string += "-" + build;
         }
 
         return string;
@@ -109,21 +162,28 @@ public class Version implements Comparab
      */
     public String simpleToString() {
         return String.format("%1$d.%2$d.%3$d",
-            this.majorRevision,
-            this.minorRevision,
-            this.maintenanceRevision);
+            majorVersion,
+            minorVersion,
+            maintenanceVersion);
     }
 
+    /**
+     * Decode a string into the version parts.
+     *
+     * @param string The input string in a format recognizable as a version 
string.
+     * @return       The new version object constructed from the string 
information.
+     */
     public static Version decode(final String string) {
         Version version = null;
 
-        short majorRevision = 0;
-        short minorRevision = 0;
-        short maintenanceRevision = 0;
-        long updateRevision = 0;
-        String build = null;
+        short major = 0;
+        short minor = 0;
+        short maintenance = 0;
+        long update = 0;
+        String buildString = null;
 
         String revision;
+
         // Some "version" strings separate fields with a space
         // While Java 9 uses a new scheme where "build" uses a "+"
         String[] parts = string.split("[ +\\-]");
@@ -132,38 +192,58 @@ public class Version implements Comparab
         } else {
             int len = parts[0].length();
             revision = string.substring(0, len);
-            build = string.substring(len + 1);
+            buildString = string.substring(len + 1);
         }
 
         String[] revisionNumbers = revision.split("\\.");
 
         if (revisionNumbers.length > 0) {
-            majorRevision = Short.parseShort(revisionNumbers[0]);
+            major = Short.parseShort(revisionNumbers[0]);
 
             if (revisionNumbers.length > 1) {
-                minorRevision = Short.parseShort(revisionNumbers[1]);
+                minor = Short.parseShort(revisionNumbers[1]);
 
                 if (revisionNumbers.length > 2) {
-                    String[] maintenanceRevisionNumbers = 
revisionNumbers[2].split("[_\\-]");
+                    String[] maintenanceVersionNumbers = 
revisionNumbers[2].split("[_\\-]");
 
-                    if (maintenanceRevisionNumbers.length > 0) {
-                        maintenanceRevision = 
Short.parseShort(maintenanceRevisionNumbers[0]);
+                    if (maintenanceVersionNumbers.length > 0) {
+                        maintenance = 
Short.parseShort(maintenanceVersionNumbers[0]);
 
-                        if (maintenanceRevisionNumbers.length > 1) {
-                            updateRevision = 
Long.parseLong(maintenanceRevisionNumbers[1]);
+                        if (maintenanceVersionNumbers.length > 1) {
+                            update = 
Long.parseLong(maintenanceVersionNumbers[1]);
                         }
                     }
                 }
             }
 
-            version = new Version(majorRevision, minorRevision, 
maintenanceRevision,
-                updateRevision, build);
+            version = new Version(major, minor, maintenance, update, 
buildString);
         }
 
         return version;
     }
 
     /**
+     * Added so that any unexpected version string formats that might cause an 
error
+     * will not also cause the application to fail to start.
+     *
+     * @param versionString A potential version string to parse/decode.
+     * @return The parsed version information (if possible), or an empty 
version
+     * (that will look like: "0.0.0_00") if there was a parsing problem of any 
kind.
+     */
+    public static Version safelyDecode(final String versionString) {
+        if (!Utils.isNullOrEmpty(versionString)) {
+            try {
+                return decode(versionString);
+            } catch (Throwable ex) {
+                String exMsg = ExceptionUtils.toString(ex);
+                System.err.println("Error decoding version string \"" + 
versionString + "\": " + exMsg);
+            }
+        }
+        return ZERO_VERSION;
+    }
+
+
+    /**
      * Decode the implementation version found in our jar file manifest into
      * a {@link Version} object.
      *

Modified: pivot/trunk/core/test/org/apache/pivot/util/test/VersionTest.java
URL: 
http://svn.apache.org/viewvc/pivot/trunk/core/test/org/apache/pivot/util/test/VersionTest.java?rev=1889254&r1=1889253&r2=1889254&view=diff
==============================================================================
--- pivot/trunk/core/test/org/apache/pivot/util/test/VersionTest.java (original)
+++ pivot/trunk/core/test/org/apache/pivot/util/test/VersionTest.java Wed Apr 
28 05:59:50 2021
@@ -19,6 +19,7 @@ package org.apache.pivot.util.test;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -27,7 +28,13 @@ import org.junit.Test;
 import org.apache.pivot.util.Version;
 
 
+/**
+ * Tests of the {@link Version} class.
+ */
 public class VersionTest {
+    /**
+     * Test version decode that happens at application startup.
+     */
     @Test
     public void testApplicationStartup() {
         // These are the things that happen right away for ApplicationContext
@@ -54,34 +61,48 @@ public class VersionTest {
         }
     }
 
+    /** The Java version string that broke the old code (build overflows a 
byte). */
     private static final String S1_8_131 = "1.8.0_131";
+    /** Decoding that breaking version string. */
     private static final Version V1 = Version.decode(S1_8_131);
+    /** The version object that should match that decoded value. */
     private static final Version V8_131 = new Version(1, 8, 0, 131);
+    /** A version 1.0 string. */
     private static final String S1_0_0 = "1.0.0_00";
+    /** Decoding version 1. */
     private static final Version V0 = Version.decode(S1_0_0);
+    /** The version object that should match version 1. */
     private static final Version V1_0 = new Version(1, 0, 0, 0);
+    /** The null/empty version object. */
+    private static final Version EMPTY = new Version(0, 0, 0, 0);
 
+    /**
+     * Test basic parsing (including our overflow fail case).
+     */
     @Test
     public void testVersionParsing() {
-        assertEquals("version decode", V1, V8_131);
-        assertEquals("version to string", S1_8_131, V8_131.toString());
+        assertEquals("version decode", V8_131, V1);
+        assertEquals("version to string", V8_131.toString(), S1_8_131);
 
-        assertEquals("version 0 decode", V0, V1_0);
-        assertEquals("version 0 to string", V1_0.toString(), S1_0_0);
+        assertEquals("version 0 decode", V1_0, V0);
+        assertEquals("version 0 to string", S1_0_0, V1_0.toString());
 
         // New Java 9 version number scheme
         String j9 = "9.0.1+11";
         Version vj9 = Version.decode(j9);
         Version vj90 = new Version(9, 0, 1, 0);
-        assertEquals("Java version 9 decode", vj9, vj90);
-        assertEquals("Java version 9 to string", vj9.toString(), 
"9.0.1_00-11");
+        assertEquals("Java version 9 decode", vj90, vj9);
+        assertEquals("Java version 9 to string", "9.0.1_00-11", 
vj9.toString());
     }
 
+    /**
+     * Test overflows of the new short values.
+     */
     @Test
     public void testLimits() {
         Version vMax = new Version(32767, 32767, 32767, 32767);
         String sMax = "32767.32767.32767_32767";
-        assertEquals("max versions", vMax.toString(), sMax);
+        assertEquals("max versions", sMax, vMax.toString());
         IllegalArgumentException argFailure = null;
         try {
             Version vOverflow = new Version(32768, 0, 1, 0);
@@ -89,23 +110,32 @@ public class VersionTest {
             argFailure = iae;
         }
         assertNotNull("illegal argument exception", argFailure);
-        assertEquals("exception message", argFailure.getMessage(),
-            "majorRevision must be less than or equal 32767.");
+        assertEquals("exception message",
+            "majorVersion must be less than or equal 32767.",
+            argFailure.getMessage());
     }
 
+    /**
+     * Test {@link Version#getNumber}.
+     */
     @Test
     public void testNumber() {
         Version vNum = new Version(2, 1, 1, 100);
         long num = vNum.getNumber();
-        System.out.format("test getNumber(): %1$s -> %2$d%n", vNum, num);
-        assertEquals("long number", num, 562954248454244L);
+        System.out.format("test getNumber(): %1$s -> %2$d (0x%2$016x)%n", 
vNum, num);
+        assertEquals("long number", 0x0002000100010064L, num);
     }
 
-    // Taken from PIVOT-996 test case
+    /** Taken from PIVOT-996 test case -- the build suffix ... */
     private static final String PIVOT_996_SUFFIX = "25.51-b14";
+    /** PIVOT-996 complete input string. */
     private static final String PIVOT_996_INPUT  = "8.1.028 " + 
PIVOT_996_SUFFIX;
+    /** What we expect from PIVOT-996 test case on output. */
     private static final String PIVOT_996_OUTPUT = "8.1.28_00-" + 
PIVOT_996_SUFFIX;
 
+    /**
+     * Other test cases (from issues, or other sources).
+     */
     @Test
     public void testOtherVersions() {
         Version jvmVersionParsed = Version.decode(PIVOT_996_INPUT);
@@ -114,10 +144,10 @@ public class VersionTest {
 
         System.out.println("Information only: our version = " + 
Version.implementationVersion());
 
-        assertEquals("PIVOT-996 test case", jvmVersionParsed, 
jvmVersionExplicit);
+        assertEquals("PIVOT-996 test case", jvmVersionExplicit, 
jvmVersionParsed);
         System.out.format("PIVOT-996 parsed/toString: %1$s, expected: %2$s%n",
             parsedToString, PIVOT_996_OUTPUT);
-        assertEquals("PIVOT-996 toString", parsedToString, PIVOT_996_OUTPUT);
+        assertEquals("PIVOT-996 toString", PIVOT_996_OUTPUT, parsedToString);
 
         Pattern versionPattern = Pattern.compile("(\\d+(\\.\\d+\\.\\d+)?).*");
         String sysJavaVersion = System.getProperty("java.runtime.version");
@@ -136,19 +166,22 @@ public class VersionTest {
         String newJava9Formatted = newJava9.toString();
         System.out.format("Potential new Java version: %1$s, parsed and 
formatted: %2$s%n",
             newJava9Version, newJava9Formatted);
-        assertEquals(newJava9Formatted, "9.0.0_00-ea+19");
+        assertEquals("new Java 9 version", "9.0.0_00-ea+19", 
newJava9Formatted);
 
         String newJava10Version = "10+-ea";
         Version newJava10 = Version.decode(newJava10Version);
         String newJava10Formatted = newJava10.toString();
         System.out.format("Potential new Java 10 version: %1$s, parsed and 
formatted: %2$s%n",
             newJava10Version, newJava10Formatted);
-        assertEquals(newJava10Formatted, "10.0.0_00--ea");
+        assertEquals("new Java 10 version", "10.0.0_00--ea", 
newJava10Formatted);
     }
 
+    /**
+     * Complete test of the new version strings possible with Java 9
+     * (taken from <a 
href="http://openjdk.java.net/jeps/223";>http://openjdk.java.net/jeps/223</a>).
+     */
     @Test
     public void testJava9Versions() {
-        // All the other suggested versions from 
"http://openjdk.java.net/jeps/223";
         String[] versions = {
             "9-ea+19",
             "9+100",
@@ -182,4 +215,18 @@ public class VersionTest {
             System.out.format("Raw %1$s -> %2$s%n", version, v.toString());
         }
     }
+
+    /**
+     * Test the new {@link Version#safelyDecode}.
+     */
+    @Test
+    public void testSafelyDecode() {
+        try {
+            Version junk = Version.safelyDecode("this is junk");
+            assertEquals("safely decode default", EMPTY, junk);
+        } catch (Exception ex) {
+            fail("safelyDecode threw an exception: " + ex.getMessage());
+        }
+    }
 }
+


Reply via email to