package com.fasterxml.jackson.core.util;
import java.io.*;
import java.util.Properties;
import java.util.regex.Pattern;
import com.fasterxml.jackson.core.Version;
/**
* Functionality for supporting exposing of component {@link Version}s.
*<p>
* Note that this class can be used in two roles: first, as a static
* utility class for loading purposes, and second, as a singleton
* loader of per-module version information.
* In latter case one must sub-class to get proper per-module instance;
* and sub-class must reside in same Java package as matching "VERSION.txt"
* file.
*/
public class VersionUtil
{
public final static String VERSION_FILE = "VERSION.txt";
private final static Pattern VERSION_SEPARATOR = Pattern.compile("[-_./;:]");
private final Version _version;
/*
/**********************************************************
/* Instance life-cycle, accesso
/**********************************************************
*/
protected VersionUtil()
{
Version v = null;
try {
/* Class we pass only matters for resource-loading: can't use this Class
* (as it's just being loaded at this point), nor anything that depends on it.
*/
v = VersionUtil.versionFor(getClass());
} catch (Exception e) { // not good to dump to stderr; but that's all we have at this low level
System.err.println("ERROR: Failed to load Version information for bundle (via "+getClass().getName()+").");
}
if (v == null) {
v = Version.unknownVersion();
}
_version = v;
}
public Version version() { return _version; }
/*
/**********************************************************
/* Static load methods
/**********************************************************
*/
/**
* Helper method that will try to load version information for specified
* class. Implementation is simple: class loader that loaded specified
* class is asked to load resource with name "VERSION" from same
* location (package) as class itself had.
* If no version information is found, {@link Version#unknownVersion()} is
* returned.
*/
public static Version versionFor(Class<?> cls)
{
InputStream in;
Version version = null;
try {
in = cls.getResourceAsStream(VERSION_FILE);
if (in != null) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
String groupStr = null, artifactStr = null;
String versionStr = br.readLine();
if (versionStr != null) {
groupStr = br.readLine();
if (groupStr != null) {
groupStr = groupStr.trim();
artifactStr = br.readLine();
if (artifactStr != null) {
artifactStr = artifactStr.trim();
}
}
}
version = parseVersion(versionStr, groupStr, artifactStr);
} finally {
try {
in.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
} catch (IOException e) { }
return (version == null) ? Version.unknownVersion() : version;
}
/**
* Will attempt to load the maven version for the given groupId and
* artifactId. Maven puts a pom.properties file in
* META-INF/maven/groupId/artifactId, containing the groupId,
* artifactId and version of the library.
*
* @param classLoader the ClassLoader to load the pom.properties file from
* @param groupId the groupId of the library
* @param artifactId the artifactId of the library
* @return The version
*/
public static Version mavenVersionFor(ClassLoader classLoader, String groupId, String artifactId) {
InputStream pomPoperties = classLoader.getResourceAsStream("META-INF/maven/" + groupId.replaceAll("\\.", "/")
+ "/" + artifactId + "/pom.properties");
if (pomPoperties != null) {
try {
Properties props = new Properties();
props.load(pomPoperties);
String versionStr = props.getProperty("version");
String pomPropertiesArtifactId = props.getProperty("artifactId");
String pomPropertiesGroupId = props.getProperty("groupId");
return parseVersion(versionStr, pomPropertiesGroupId, pomPropertiesArtifactId);
} catch (IOException e) {
// Ignore
} finally {
try {
pomPoperties.close();
} catch (IOException e) {
// Ignore
}
}
}
return Version.unknownVersion();
}
/**
* Use variant that takes three arguments instead
*
* @deprecated
*/
@Deprecated
public static Version parseVersion(String versionStr) {
return parseVersion(versionStr, null, null);
}
public static Version parseVersion(String versionStr, String groupId, String artifactId)
{
if (versionStr == null) {
return null;
}
versionStr = versionStr.trim();
if (versionStr.length() == 0) {
return null;
}
String[] parts = VERSION_SEPARATOR.split(versionStr);
int major = parseVersionPart(parts[0]);
int minor = (parts.length > 1) ? parseVersionPart(parts[1]) : 0;
int patch = (parts.length > 2) ? parseVersionPart(parts[2]) : 0;
String snapshot = (parts.length > 3) ? parts[3] : null;
return new Version(major, minor, patch, snapshot,
groupId, artifactId);
}
protected static int parseVersionPart(String partStr)
{
partStr = partStr.toString();
int len = partStr.length();
int number = 0;
for (int i = 0; i < len; ++i) {
char c = partStr.charAt(i);
if (c > '9' || c < '0') break;
number = (number * 10) + (c - '0');
}
return number;
}
}