I have a project that uses an old Cassandra driver library, which relies on deprecated features of Guava that have been removed in release 20. I was thinking about adding a test that fails when someone accidentally increases the version of Guava from 19 to 20.
How can I programmatically find out which Guava version is used?
You can get a version string from files under META-INF/ in the guava. jar. At runtime you'll need to use appropriate ClassLoader instance in order to load the META-INF/ files you want.
Guava is a suite of core and expanded libraries that include utility classes, google's collections, io classes, and much much more. Guava has only one code dependency - javax.
Guava is an open-source “Collection Library” library for Java, developed by Google. It provides utilities for working with Java collections. As you dive deep into Guava you'll notice how it reduces coding errors, facilitates standard coding practices and boost productivity by making code concise and easy to read.
Guava is a set of core Java libraries from Google that includes new collection types (such as multimap and multiset), immutable collections, a graph library, and utilities for concurrency, I/O, hashing, caching, primitives, strings, and more!
You can get a version string from files under META-INF/ in the guava.jar. At runtime you'll need to use appropriate ClassLoader
instance in order to load the META-INF/ files you want. You can either use Guava's Resources
utility class to load a resource with a unique name directly or you can iterate through resources with the same name across multiple jar
files using $someGuavaClassName.class.getClassLoader().getResources(String)
. If you go with the latter then you will need to use someGuavaClassName
that will exist in the version you are testing against. Resources
itself has been in Guava since 1.0 and I don't suspect it going anywhere anytime soon so that should be a safe class to use.
I tested the following on Guava 20.0 and 12.0 and it worked for both. I suspect it will work for all relatively recent versions of Guava:
public class GuavaVersionFetcher {
public static void main(String... args) throws IOException {
System.out.println(determineGuavaMavenVersion());
System.out.println(determineGuavaManifestVersion());
}
public static String determineGuavaMavenVersion() throws IOException {
String resourceName = "META-INF/maven/com.google.guava/guava/pom.properties";
Properties properties = new Properties();
try (InputStream inputStream = Resources.getResource(resourceName).openStream()) {
properties.load(inputStream);
}
return properties.getProperty("version");
}
public static String determineGuavaManifestVersion() throws IOException {
Enumeration<URL> resources = Resources.class.getClassLoader()
.getResources("META-INF/MANIFEST.MF");
while (resources.hasMoreElements()) {
Manifest manifest;
try (InputStream inputStream = resources.nextElement().openStream()) {
manifest = new Manifest(inputStream);
}
Attributes mainAttributes = manifest.getMainAttributes();
String symbolicName = mainAttributes.getValue("Bundle-SymbolicName");
if ("com.google.guava".equals(symbolicName)) {
return mainAttributes.getValue("Bundle-Version");
}
}
return null;
}
}
Example output:
20.0
20.0.0
Note: If the Guava team ever moves away from using Maven the first method may no longer work so I suggest using the manifest method.
I did not find a simple way to get access to the version, but here is a solution that works for me:
@Test(expected = ClassNotFoundException.class)
public void mustNotUpgradeToGuava20_asItIsIncompatibleWithCassandra() throws ClassNotFoundException {
Class.forName("com.google.common.graph.Graph");
}
This test passes up to Guava 19 and will fail with Guava 20. The Graph
class is just the first hit of added classes that I found in the release notes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With