All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tangosol.util.VersionHelper Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2024, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * https://oss.oracle.com/licenses/upl.
 */

package com.tangosol.util;

import java.util.Arrays;

/**
 * A utility class for working with Coherence versions.
 */
public class VersionHelper
    {

    /**
     * Convert the version elements into a single integer value.
     *
     * @param nYear   the version year
     * @param nMonth  the version month
     * @param nPatch  the version patch
     *
     * @return  the yy-mm-patch version encoded as an int
     */
    public static int encodeVersion(int nYear, int nMonth, int nPatch)
        {
        // 64(0x3F)-based - 5 elements 6 bits each

        // the version prefix (e.g. 14.1.1 or 14.1.2) consumes the first 3 elements
        // with the remainder used for year, month and patch

        nPatch = (nMonth > 6 ? 0x1 << 5 : 0x0) | (nPatch & 0x1F);

        return getVersionPrefix(nYear, nMonth)
            | ((nYear & 0x3F) << 6)
            | (nPatch & 0x3F);
        }

    /**
     * Convert the version elements into a single integer value.
     *
     * @param nMajor     the major version number
     * @param nMinor     the minor version number
     * @param nMicro     the micro version number
     * @param nPatchSet  the patch set version number
     * @param nPatch     the patch version number
     *
     * @return  the version encoded as an int
     */
    public static int encodeVersion(int nMajor, int nMinor, int nMicro, int nPatchSet, int nPatch)
        {
        // 64(0x3F)-based - 5 elements 6 bits each

        if (nPatchSet > 2000)
            {
            // Assume this is a feature pack version
            int nPrefix = encodeVersion(nMajor, nMinor, nMicro, 0, 0);
            int nYear   = nPatchSet / 100;
            return nPrefix
                | ((nYear & 0x3F) << 6)
                | (nPatch & 0x3F);
            }

        return ((nMajor   & 0x3F) << 6*4)
            | ((nMinor    & 0x3F) << 6*3)
            | ((nMicro    & 0x3F) << 6*2)
            | ((nPatchSet & 0x3F) << 6)
            | (nPatch     & 0x3F);
        }

    /**
     * Return the version prefix for a given yy-mm version.
     *
     * @param nYear   the version year
     * @param nMonth  the version month
     *
     * @return  the version prefix
     */
    public static int getVersionPrefix(int nYear, int nMonth)
        {
        if (nYear > 23)
            {
            return encodeVersion(15, 0, 0, 0, 0);
            }
        return encodeVersion(14, 1, 1, 0, 0);
        }

    /**
     * Return {@code true} if the provided part of the version could represent a year.
     *
     * @param nVersion  the version part to check
     *
     * @return {@code true} if the provided part of the version could represent a year
     */
    public static boolean isCalendarVersion(int nVersion)
        {
        return nVersion >= 20; // 2020 was the first use of calendar versions
        }

    /**
     * Parse the specified version string and generate an internal integer
     * representation.
     *
     * @param sVersion  the version string to encode
     *
     * @return the version string encoded to an {@code int}
     */
    public static int parseVersion(String sVersion)
        {
        // import java.util.Arrays;

        if (sVersion == null || sVersion.isEmpty())
            {
            return 0;
            }

        // the format of the version string is
        //   major.minor.micro.patch-set.patch []
        //          or
        //   major.minor.micro.year.month.patch

        // for example:
        //   "12.2.1.1.0" or "12.2.3.0.0 internal build"
        //          or
        //   "14.1.1.20.06.0" or "14.1.1.20.06.0 internal build"
        //          or feature pack version
        //   "14.1.1.2006.0" or "14.1.1.2006.0 internal build"

        // (optional suffix could come from the "Implementation-Description"
        // element of the manifest; see Coherence._initStatic)

        // remove an optional suffix first
        int ofSuffix = sVersion.indexOf(" ");
        if (ofSuffix > 0)
            {
            sVersion = sVersion.substring(0, ofSuffix);
            }

        final int INDEX_YEAR  = 3; // 14.1.1.20.06.01
        final int INDEX_MONTH = 4; // 14.1.1.20.06.01

        String[] asVersions = sVersion.split("\\.");
        int[]    an         = new int[5];

        // handle feature pack which condenses YY && MM into a single string
            {
            String sYear = asVersions.length > INDEX_YEAR ? asVersions[INDEX_YEAR] : "";
            if (sYear.length() >= 4) // YYMM
                {
                asVersions = Arrays.copyOf(asVersions, asVersions.length + 1);

                // right shift
                for (int i = asVersions.length - 2; i > INDEX_YEAR; --i)
                    {
                    asVersions[i + 1] = asVersions[i];
                    asVersions[i]     = null;
                    }

                asVersions[INDEX_YEAR]  = sYear.substring(0, 2);
                asVersions[INDEX_MONTH] = sYear.substring(2);
                }
            }

        // process the version converting to 5 base 64 encoded integers
        for (int i = 0, c = Math.min(an.length, asVersions.length); i < c; i++)
            {
            try
                {
                // the range of the version part is 0 .. 63
                int nVersion = Integer.parseInt(asVersions[i]);

                if (i == INDEX_MONTH && isCalendarVersion(an[i - 1]))
                    {
                    nVersion = nVersion > 6
                            ? 0x1 << 5
                            : 0x0;

                    nVersion |= i + 1 < asVersions.length
                                ? Integer.parseInt(asVersions[i + 1])
                                : 0;
                    }

                an[i] = Math.min(63, nVersion);
                }
            catch (NumberFormatException e)
                {
                // un-parsable part; leave as zero
                }
            }

        return encodeVersion(an[0], an[1], an[2], an[3], an[4]);
        }


    /**
     * Create an array of version elements, where index 0 is "major", 1 is
     * "minor", ... 4 is "patch".
     */
    public static int[] toVersionArray(String sVersion)
        {
        // 64-based - 5 elements 6 bits each

        int nVersion = parseVersion(sVersion);
        return new int[]
            {
            (nVersion & 0x3F000000) >> 6*4,
            (nVersion & 0x00FC0000) >> 6*3,
            (nVersion & 0x0003F000) >> 6*2,
            (nVersion & 0x00000FC0) >> 6,
            (nVersion & 0x0000003F),
            };
        }

    /**
     * Create a string representation of the specified version in internal
     * encoding.
     */
    public static String toVersionString(int nVersion, boolean fIncludePrefix)
        {
        // nVersion is 64-based: 5 elements with 6 bits each

        int nYear  = (nVersion & 0x00000FC0) >> 6;
        int nPatch = nVersion & 0x0000003F;

        String sVersion = (fIncludePrefix || !isCalendarVersion(nYear)
                ? ((nVersion & 0x3F000000) >> 6*4) + "." +
                  ((nVersion & 0x00FC0000) >> 6*3) + "." +
                  ((nVersion & 0x0003F000) >> 6*2) + "."
                : "") + nYear;

        if (isCalendarVersion(nYear))
            {
            int nPatchActual = nPatch & ~0x20;

            sVersion += (fIncludePrefix ? "" : ".");
            if ((nPatch & 0x20) == 0)
                {
                // display 6 for feature packs in years before 22 and 03 for years beyond
                sVersion += (nYear <= 22 ? "06" : "03");
                }
            else
                {
                // display 12 for feature packs in years before 21 and 09 for years beyond
                sVersion += (nYear <= 21 ? "12" : "09");
                }

            sVersion += "." + nPatchActual;
            }
        else
            {
            sVersion += "." + nPatch;
            }

        return sVersion;
        }

    /**
     * Return {@code true} iff the actual version provided is greater than or equal
     * to the required version.
     *
     * @param nRequired  the required version in its encoded form
     * @param nActual    the actual version in its encoded form
     *
     * @return {@code true} iff the actual version provided is greater than or equal
     *         to the required version
     */
    public static boolean isVersionCompatible(int nRequired, int nActual)
        {
        return nRequired <= nActual;
        }

    /**
     * Return {@code true} iff the required and the actual versions provided have
     * the identical base version, and the actual patch version is greater or equal
     * to the required patch version.
     *
     * @param nRequired  the required version in its encoded form
     * @param nActual    the actual version in its encoded form
     *
     * @return {@code true} iff the required and the actual versions provided have
     *         the identical base version, and the actual patch version is greater or equal
     *         to the required patch version
     */
    public static boolean isPatchCompatible(int nRequired, int nActual)
        {
        return (nRequired & ~0x3F) == (nActual & ~0x3F) && (nRequired & 0x3F) <= (nActual & 0x3F);
        }

    /**
     * Compare two version strings for compatability.
     * 

* The first string is the version to test, the second is the version required. * If the second version is compatible with the first, then "pass" is displayed * otherwise "fail" is displayed. * * @param args the two version strings to compare */ public static void main(String[] args) { if (args.length == 2) { String sVersionOne = args[0]; String sVersionTwo = args[1]; int nEncodedOne = VersionHelper.parseVersion(sVersionOne.replace("-", ".")); int nEncodedTwo = VersionHelper.parseVersion(sVersionTwo.replace("-", ".")); int nExitCode; if (VersionHelper.isVersionCompatible(nEncodedTwo, nEncodedOne)) { System.out.println("pass"); nExitCode = 0; } else { System.out.println("fail"); nExitCode = 1; } if (Boolean.getBoolean("no.exit.code")) { nExitCode = 0; } System.exit(nExitCode); } System.err.println("Usage:"); System.err.println("VersionHelper "); System.err.println(); System.err.println("Displays \"pass\" if is compatible with "); System.err.println("Displays \"fail\" if is not compatible with "); System.err.println(); System.err.println("Exit code zero, versionCheck is compatible with versionRequired"); System.err.println("Exit code one, versionCheck is not compatible with versionRequired"); System.err.println("Exit code two, incorrect version arguments were specified"); System.err.println(); System.err.println("If the no.exit.code system property is set to true, the exit code will be zero regardless of a pass or fail."); System.err.println(); System.exit(2); } // ----- constants ------------------------------------------------------ /** * The encoded CE 23.09.0 and 1 versions. */ public static final int VERSION_23_09 = encodeVersion(23, 9, 0); public static final int VERSION_23_09_1 = encodeVersion(23, 9, 1); /** * The encoded 14.1.1.2206.0, 6 and 7 versions. */ public static final int VERSION_14_1_1_2206 = encodeVersion(14, 1, 1, 2206, 0); public static final int VERSION_14_1_1_2206_6 = encodeVersion(14, 1, 1, 2206, 6); public static final int VERSION_14_1_1_2206_7 = encodeVersion(14, 1, 1, 2206, 7); /** * The encoded 14.1.2.0.0 version. */ public static final int VERSION_14_1_2_0 = encodeVersion(14, 1, 2, 0, 0); /** * The encoded 14.1.1.0.0 and 16 versions. */ public static final int VERSION_14_1_1_0 = encodeVersion(14, 1, 1, 0, 0); public static final int VERSION_14_1_1_0_16 = encodeVersion(14, 1, 1, 0, 16); public static final int VERSION_14_1_1_0_17 = encodeVersion(14, 1, 1, 0, 17); /** * The encoded 12.2.1.4.0 and 20 versions. */ public static final int VERSION_12_2_1_4 = encodeVersion(12, 2, 1, 4, 0); public static final int VERSION_12_2_1_4_20 = encodeVersion(12, 2, 1, 4, 20); public static final int VERSION_12_2_1_4_21 = encodeVersion(12, 2, 1, 4, 21); /** * The encoded 12.2.1.6.0 and 6 versions. */ public static final int VERSION_12_2_1_6 = encodeVersion(12, 2, 1, 6, 0); public static final int VERSION_12_2_1_6_6 = encodeVersion(12, 2, 1, 6, 6); public static final int VERSION_12_2_1_6_7 = encodeVersion(12, 2, 1, 6, 7); }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy