org.apache.aries.util.VersionRange Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIESOR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.aries.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.aries.util.internal.MessageUtil;
import org.osgi.framework.Version;
public final class VersionRange {
/** A string representation of the version. */
private String version;
/** The minimum desired version for the bundle */
private Version minimumVersion;
/** The maximum desired version for the bundle */
private Version maximumVersion;
/** True if the match is exclusive of the minimum version */
private boolean minimumExclusive;
/** True if the match is exclusive of the maximum version */
private boolean maximumExclusive;
/** A regexp to select the version */
private static final Pattern versionCapture = Pattern.compile("\"?(.*?)\"?$");
/**
*
* @param version
* version for the verioninfo
*/
public VersionRange(String version) {
this.version = version;
processVersionAttribute(version);
}
/**
* This method should be used to create a version range from a single
* version string.
* @param version
* version for the versioninfo
* @param exactVersion
* whether this is an exact version {@code true} or goes to infinity
* {@code false}
*/
public VersionRange(String version, boolean exactVersion) {
if (exactVersion) {
// Do not store this string as it might be just a version, or a range!
processExactVersionAttribute(version);
} else {
this.version = version;
processVersionAttribute(this.version);
}
assertInvariants();
}
/**
* Constructor designed for internal use only.
*
* @param maximumVersion
* @param maximumExclusive
* @param minimumVersion
* @param minimumExclusive
* @throws IllegalArgumentException
* if parameters are not valid.
*/
private VersionRange(Version maximumVersion,
boolean maximumExclusive,
Version minimumVersion,
boolean minimumExclusive) {
this.maximumVersion = maximumVersion;
this.maximumExclusive = maximumExclusive;
this.minimumVersion = minimumVersion;
this.minimumExclusive = minimumExclusive;
assertInvariants();
}
/*
* (non-Javadoc)
*
* @see org.apache.aries.application.impl.VersionRange#toString()
*/
@Override
public String toString() {
// Some constructors don't take in a string that we can return directly,
// so construct one if needed
if (version == null) {
if (maximumVersion == null) {
version = minimumVersion.toString();
} else {
version = (minimumExclusive ? "(" : "[") + minimumVersion + "," + maximumVersion
+ (maximumExclusive ? ")" : "]");
}
}
return this.version;
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + minimumVersion.hashCode();
result = 31 * result + (minimumExclusive ? 1 : 0);
result = 31 * result + (maximumVersion != null ? maximumVersion.hashCode() : 0);
result = 31 * result + (maximumExclusive ? 1 : 0);
return result;
}
@Override
public boolean equals(Object other) {
boolean result = false;
if (this == other) {
result = true;
} else if (other instanceof VersionRange) {
VersionRange vr = (VersionRange) other;
result = minimumVersion.equals(vr.minimumVersion)
&& minimumExclusive == vr.minimumExclusive
&& (maximumVersion == null ? vr.maximumVersion == null : maximumVersion
.equals(vr.maximumVersion)) && maximumExclusive == vr.maximumExclusive;
}
return result;
}
/**
* this method returns the exact version from the versionInfo obj.
* this is used for DeploymentContent only to return a valid exact version
* otherwise, null is returned.
* @return the exact version
*/
public Version getExactVersion() {
Version v = null;
if (isExactVersion()) {
v = getMinimumVersion();
}
return v;
}
/**
* get the maximum version
* @return the maximum version
*/
public Version getMaximumVersion() {
return maximumVersion;
}
/**
* get the minimum version
* @return the minimum version
*/
public Version getMinimumVersion() {
return minimumVersion;
}
/**
* is the maximum version exclusive
* @return is the max version in the range.
*/
public boolean isMaximumExclusive() {
return maximumExclusive;
}
/**
* is the maximum version unbounded
* @return true if no upper bound was specified.
*/
public boolean isMaximumUnbounded() {
boolean unbounded = maximumVersion == null;
return unbounded;
}
/**
* is the minimum version exclusive
* @return true if the min version is in range.
*/
public boolean isMinimumExclusive() {
return minimumExclusive;
}
/**
* this is designed for deployed-version as that is the exact version.
*
* @param version
* @return
* @throws IllegalArgumentException
*/
private boolean processExactVersionAttribute(String version) throws IllegalArgumentException {
boolean success = processVersionAttribute(version);
if (maximumVersion == null) {
maximumVersion = minimumVersion;
}
if (!minimumVersion.equals(maximumVersion)) {
throw new IllegalArgumentException(MessageUtil.getMessage("UTIL0011E", version));
}
if (!!!isExactVersion()) {
throw new IllegalArgumentException(MessageUtil.getMessage("UTIL0009E", version));
}
return success;
}
/**
* process the version attribute,
*
* @param version
* the value to be processed
* @return
* @throws IllegalArgumentException
*/
private boolean processVersionAttribute(String version) throws IllegalArgumentException {
boolean success = false;
if (version == null) {
throw new IllegalArgumentException(MessageUtil.getMessage("UTIL0010E"));
}
Matcher matches = versionCapture.matcher(version);
if (matches.matches()) {
String versions = matches.group(1);
if ((versions.startsWith("[") || versions.startsWith("("))
&& (versions.endsWith("]") || versions.endsWith(")"))) {
if (versions.startsWith("["))
minimumExclusive = false;
else if (versions.startsWith("("))
minimumExclusive = true;
if (versions.endsWith("]"))
maximumExclusive = false;
else if (versions.endsWith(")"))
maximumExclusive = true;
int index = versions.indexOf(',');
String minVersion = versions.substring(1, index);
String maxVersion = versions.substring(index + 1, versions.length() - 1);
try {
minimumVersion = new Version(minVersion.trim());
maximumVersion = new Version(maxVersion.trim());
success = true;
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException(MessageUtil.getMessage("UTIL0009E", version), nfe);
}
} else {
try {
if (versions.trim().length() == 0)
minimumVersion = new Version(0, 0, 0);
else
minimumVersion = new Version(versions.trim());
success = true;
} catch (NumberFormatException nfe) {
throw new IllegalArgumentException(MessageUtil.getMessage("UTIL0009E", version), nfe);
}
}
} else {
throw new IllegalArgumentException(MessageUtil.getMessage("UTIL0009E", version));
}
return success;
}
/**
* Assert object invariants. Called by constructors to verify that arguments
* were valid.
*
* @throws IllegalArgumentException
* if invariants are violated.
*/
private void assertInvariants() {
if (minimumVersion == null
|| !isRangeValid(minimumVersion, minimumExclusive, maximumVersion, maximumExclusive)) {
IllegalArgumentException e = new IllegalArgumentException();
throw e;
}
}
/**
* Check if the supplied parameters describe a valid version range.
*
* @param min
* the minimum version.
* @param minExclusive
* whether the minimum version is exclusive.
* @param max
* the maximum version.
* @param maxExclusive
* whether the maximum version is exclusive.
* @return true is the range is valid; otherwise false.
*/
private boolean isRangeValid(Version min,
boolean minExclusive,
Version max,
boolean maxExclusive) {
boolean result;
// A null maximum version is unbounded so means that minimum is smaller
// than
// maximum.
int minMaxCompare = (max == null ? -1 : min.compareTo(max));
if (minMaxCompare > 0) {
// Minimum larger than maximum is invalid.
result = false;
} else if (minMaxCompare == 0 && (minExclusive || maxExclusive)) {
// If min and max are the same, and either are exclusive, no valid
// range
// exists.
result = false;
} else {
// Range is valid.
result = true;
}
return result;
}
/**
* This method checks that the provided version matches the desired version.
*
* @param version
* the version.
* @return true if the version matches, false otherwise.
*/
public boolean matches(Version version) {
boolean result;
if (this.getMaximumVersion() == null) {
result = this.getMinimumVersion().compareTo(version) <= 0;
} else {
int minN = this.isMinimumExclusive() ? 0 : 1;
int maxN = this.isMaximumExclusive() ? 0 : 1;
result = (this.getMinimumVersion().compareTo(version) < minN)
&& (version.compareTo(this.getMaximumVersion()) < maxN);
}
return result;
}
/**
* check if the versioninfo is the exact version
* @return true if the range will match 1 exact version.
*/
public boolean isExactVersion() {
return minimumVersion.equals(maximumVersion) && minimumExclusive == maximumExclusive
&& !!!minimumExclusive;
}
/**
* Create a new version range that is the intersection of {@code this} and the argument.
* In other words, the largest version range that lies within both {@code this} and
* the parameter.
* @param r a version range to be intersected with {@code this}.
* @return a new version range, or {@code null} if no intersection is possible.
*/
public VersionRange intersect(VersionRange r) {
// Use the highest minimum version.
final Version newMinimumVersion;
final boolean newMinimumExclusive;
int minCompare = minimumVersion.compareTo(r.getMinimumVersion());
if (minCompare > 0) {
newMinimumVersion = minimumVersion;
newMinimumExclusive = minimumExclusive;
} else if (minCompare < 0) {
newMinimumVersion = r.getMinimumVersion();
newMinimumExclusive = r.isMinimumExclusive();
} else {
newMinimumVersion = minimumVersion;
newMinimumExclusive = (minimumExclusive || r.isMinimumExclusive());
}
// Use the lowest maximum version.
final Version newMaximumVersion;
final boolean newMaximumExclusive;
// null maximum version means unbounded, so the highest possible value.
if (maximumVersion == null) {
newMaximumVersion = r.getMaximumVersion();
newMaximumExclusive = r.isMaximumExclusive();
} else if (r.getMaximumVersion() == null) {
newMaximumVersion = maximumVersion;
newMaximumExclusive = maximumExclusive;
} else {
int maxCompare = maximumVersion.compareTo(r.getMaximumVersion());
if (maxCompare < 0) {
newMaximumVersion = maximumVersion;
newMaximumExclusive = maximumExclusive;
} else if (maxCompare > 0) {
newMaximumVersion = r.getMaximumVersion();
newMaximumExclusive = r.isMaximumExclusive();
} else {
newMaximumVersion = maximumVersion;
newMaximumExclusive = (maximumExclusive || r.isMaximumExclusive());
}
}
VersionRange result;
if (isRangeValid(newMinimumVersion, newMinimumExclusive, newMaximumVersion,
newMaximumExclusive)) {
result = new VersionRange(newMaximumVersion, newMaximumExclusive, newMinimumVersion,
newMinimumExclusive);
} else {
result = null;
}
return result;
}
/**
* Parse a version range..
*
* @param s
* @return VersionRange object.
* @throws IllegalArgumentException
* if the String could not be parsed as a VersionRange
*/
public static VersionRange parseVersionRange(String s) throws IllegalArgumentException {
return new VersionRange(s);
}
/**
* Parse a version range and indicate if the version is an exact version
*
* @param s
* @param exactVersion
* @return VersionRange object.
* @throws IllegalArgumentException
* if the String could not be parsed as a VersionRange
*/
public static VersionRange parseVersionRange(String s, boolean exactVersion)
throws IllegalArgumentException {
return new VersionRange(s, exactVersion);
}
}