blob: c9fceee34a1df3fb1e973f0d4a18ac25ed700858 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.start;
/**
* Utility class for parsing and comparing version strings.
* <p>
* http://www.oracle.com/technetwork/java/javase/namechange-140185.html
*/
public class Version implements Comparable<Version>
{
/**
* The major version for java is always "1" (per
* <a href="http://www.oracle.com/technetwork/java/javase/namechange-140185.html">legacy versioning history</a>)
*/
private int legacyMajor = 0;
/**
* The true major version is the second value ("1.5" == "Java 5", "1.8" = "Java 8", etc..)
*/
private int major = -1;
/**
* The revision of the version.
* <p>
* This value is always "0" (also per <a
* href="http://www.oracle.com/technetwork/java/javase/namechange-140185.html">legacy versioning history</a>)
*/
private int revision = -1;
/**
* The update (where bug fixes are placed)
*/
private int update = -1;
/**
* Extra versioning information present on the version string, but not relevant for version comparison reason.
* (eg: with "1.8.0_45-internal", the suffix would be "-internal")
*/
private String suffix = "";
private static enum ParseState
{
LEGACY,
MAJOR,
REVISION,
UPDATE;
}
public Version(String versionString)
{
parse(versionString);
}
@Override
/**
* Compares with other version. Does not take extension into account, as there is no reliable way to order them.
*
* @param other the other version to compare this to
* @return -1 if this is older version that other, 0 if its same version, 1 if it's newer version than other
*/
public int compareTo(Version other)
{
if (other == null)
{
throw new NullPointerException("other version is null");
}
if (this.legacyMajor < other.legacyMajor)
{
return -1;
}
if (this.legacyMajor > other.legacyMajor)
{
return 1;
}
if (this.major < other.major)
{
return -1;
}
if (this.major > other.major)
{
return 1;
}
if (this.revision < other.revision)
{
return -1;
}
if (this.revision > other.revision)
{
return 1;
}
if (this.update < other.update)
{
return -1;
}
if (this.update > other.update)
{
return 1;
}
return 0;
}
public int getLegacyMajor()
{
return legacyMajor;
}
public int getMajor()
{
return major;
}
public int getRevision()
{
return revision;
}
public int getUpdate()
{
return update;
}
public String getSuffix()
{
return suffix;
}
public boolean isNewerThan(Version other)
{
return compareTo(other) == 1;
}
public boolean isNewerThanOrEqualTo(Version other)
{
int comp = compareTo(other);
return (comp == 0) || (comp == 1);
}
public boolean isOlderThan(Version other)
{
return compareTo(other) == -1;
}
public boolean isOlderThanOrEqualTo(Version other)
{
int comp = compareTo(other);
return (comp == 0) || (comp == -1);
}
/**
* Check whether this version is in range of versions specified
*
* @param low
* the low part of the range
* @param high
* the high part of the range
* @return true if this version is within the provided range
*/
public boolean isInRange(Version low, Version high)
{
return ((compareTo(low) >= 0) && (compareTo(high) <= 0));
}
/**
* parses version string in the form legacy[.major[.revision[_update[-suffix]]]] into this instance.
*
* @param versionStr
* the version string
*/
private void parse(String versionStr)
{
legacyMajor = 0;
major = -1;
revision = -1;
update = -1;
suffix = "";
ParseState state = ParseState.LEGACY;
int offset = 0;
int len = versionStr.length();
int val = 0;
while (offset < len)
{
char c = versionStr.charAt(offset);
boolean isSeparator = !Character.isLetterOrDigit(c);
if (isSeparator)
{
val = 0;
}
else if (Character.isDigit(c))
{
val = (val * 10) + (c - '0');
}
else if (Character.isLetter(c))
{
suffix = versionStr.substring(offset);
return;
}
switch (state)
{
case LEGACY:
if (isSeparator)
state = ParseState.MAJOR;
else
legacyMajor = val;
break;
case MAJOR:
if (isSeparator)
state = ParseState.REVISION;
else
major = val;
break;
case REVISION:
if (isSeparator)
state = ParseState.UPDATE;
else
revision = val;
break;
case UPDATE:
if (!isSeparator)
update = val;
break;
}
offset++;
}
}
/**
* @return string representation of this version
*/
@Override
public String toString()
{
StringBuffer sb = new StringBuffer(10);
sb.append(legacyMajor);
if (major >= 0)
{
sb.append('.').append(major);
if (revision >= 0)
{
sb.append('.').append(revision);
if (update >= 0)
{
sb.append('_').append(update);
}
}
}
if (Utils.isNotBlank(suffix))
{
sb.append('-').append(suffix);
}
return sb.toString();
}
/**
* Return short string form (without suffix)
* @return string the short version string form
*/
public String toShortString()
{
StringBuffer sb = new StringBuffer(10);
sb.append(legacyMajor);
if (major >= 0)
{
sb.append('.').append(major);
if (revision >= 0)
{
sb.append('.').append(revision);
if (update >= 0)
{
sb.append('_').append(update);
}
}
}
return sb.toString();
}
}