com.datastax.driver.core.PlatformInfoFinder Maven / Gradle / Ivy
Show all versions of driver-cql-shaded Show documentation
/*
* Copyright DataStax, Inc.
*
* This software can be used solely with DataStax Enterprise. Please consult the license at
* http://www.datastax.com/terms/datastax-dse-driver-license-terms
*/
package com.datastax.driver.core;
import static com.datastax.driver.core.InsightsSchema.InsightsPlatformInfo;
import static com.datastax.driver.core.InsightsSchema.InsightsPlatformInfo.CPUS;
import static com.datastax.driver.core.InsightsSchema.InsightsPlatformInfo.OS;
import static com.datastax.driver.core.InsightsSchema.InsightsPlatformInfo.RuntimeAndCompileTimeVersions;
import com.datastax.driver.core.utils.MoreObjects;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Pattern;
class PlatformInfoFinder {
static final String UNVERIFIED_RUNTIME_VERSION = "UNVERIFIED";
private static final String MAVEN_IGNORE_LINE = "The following files have been resolved:";
private static final Pattern DEPENDENCY_SPLIT_REGEX = Pattern.compile(":");
private static final String UNKNOWN = "UNKNOWN";
private final Function propertiesUrlProvider;
private static final Function M2_PROPERTIES_PROVIDER =
new Function() {
@Override
public URL apply(DependencyInfo d) {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if (contextClassLoader == null) {
contextClassLoader = PlatformInfoFinder.class.getClassLoader();
}
return contextClassLoader.getResource(
"META-INF/maven/" + d.groupId + "/" + d.artifactId + "/pom.properties");
}
};
PlatformInfoFinder() {
this(M2_PROPERTIES_PROVIDER);
}
@VisibleForTesting
PlatformInfoFinder(Function pomPropertiesUrlProvider) {
this.propertiesUrlProvider = pomPropertiesUrlProvider;
}
InsightsPlatformInfo getInsightsPlatformInfo() {
OS os = getOsInfo();
CPUS cpus = getCpuInfo();
Map> runtimeInfo = getRuntimeInfo();
return new InsightsPlatformInfo(os, cpus, runtimeInfo);
}
private Map> getRuntimeInfo() {
Map coreDeps =
fetchDependenciesFromFile(
this.getClass().getResourceAsStream("/com/datastax/driver/core/deps.txt"));
Map graphDeps =
fetchDependenciesFromFile(
this.getClass().getResourceAsStream("/com/datastax/dse/graph/api/deps.txt"));
Map mappingDeps =
fetchDependenciesFromFile(
this.getClass().getResourceAsStream("/com/datastax/driver/mapping/deps.txt"));
Map extrasDeps =
fetchDependenciesFromFile(
this.getClass().getResourceAsStream("/com/datastax/driver/extras/codecs/deps.txt"));
Map> runtimeDependencies =
new LinkedHashMap>();
putIfNonEmpty(coreDeps, runtimeDependencies, "core");
putIfNonEmpty(graphDeps, runtimeDependencies, "graph");
putIfNonEmpty(mappingDeps, runtimeDependencies, "mapping");
putIfNonEmpty(extrasDeps, runtimeDependencies, "extras");
addJavaVersion(runtimeDependencies);
return runtimeDependencies;
}
private void putIfNonEmpty(
Map moduleDependencies,
Map> runtimeDependencies,
String moduleName) {
if (!moduleDependencies.isEmpty()) {
runtimeDependencies.put(moduleName, moduleDependencies);
}
}
@VisibleForTesting
void addJavaVersion(Map> runtimeDependencies) {
Package javaPackage = Runtime.class.getPackage();
Map javaDependencies =
new LinkedHashMap();
javaDependencies.put(
"version", toSameRuntimeAndCompileVersion(javaPackage.getImplementationVersion()));
javaDependencies.put(
"vendor", toSameRuntimeAndCompileVersion(javaPackage.getImplementationVendor()));
javaDependencies.put(
"title", toSameRuntimeAndCompileVersion(javaPackage.getImplementationTitle()));
putIfNonEmpty(javaDependencies, runtimeDependencies, "java");
}
private RuntimeAndCompileTimeVersions toSameRuntimeAndCompileVersion(String version) {
return new RuntimeAndCompileTimeVersions(version, version, false);
}
/**
* Method is fetching dependencies from file. Lines in file should be in format:
* com.organization:artifactId:jar:1.2.0 or com.organization:artifactId:jar:native:1.2.0
*
* For such file the output will be: Map
* "com.organization:artifactId",{"runtimeVersion":"1.2.0", "compileVersion:"1.2.0", "optional":
* false} Duplicates will be omitted. If there are two dependencies for the exactly the same
* organizationId:artifactId it is not deterministic which version will be taken. In the case of
* an error while opening file this method will fail silently returning an empty Map
*/
Map fetchDependenciesFromFile(InputStream inputStream) {
Map dependencies =
new LinkedHashMap();
if (inputStream == null) {
return dependencies;
}
try {
List dependenciesFromFile = extractMavenDependenciesFromFile(inputStream);
for (DependencyInfo d : dependenciesFromFile) {
dependencies.put(formatDependencyName(d), getRuntimeAndCompileVersion(d));
}
} catch (IOException e) {
return dependencies;
}
return dependencies;
}
private RuntimeAndCompileTimeVersions getRuntimeAndCompileVersion(DependencyInfo d) {
URL url = propertiesUrlProvider.apply(d);
if (url == null) {
return new RuntimeAndCompileTimeVersions(
UNVERIFIED_RUNTIME_VERSION, d.getVersion(), d.isOptional());
}
Properties properties = new Properties();
try {
properties.load(url.openStream());
} catch (IOException e) {
return new RuntimeAndCompileTimeVersions(
UNVERIFIED_RUNTIME_VERSION, d.getVersion(), d.isOptional());
}
Object version = properties.get("version");
if (version == null) {
return new RuntimeAndCompileTimeVersions(
UNVERIFIED_RUNTIME_VERSION, d.getVersion(), d.isOptional());
} else {
return new RuntimeAndCompileTimeVersions(version.toString(), d.getVersion(), d.isOptional());
}
}
private String formatDependencyName(DependencyInfo d) {
return String.format("%s:%s", d.getGroupId(), d.getArtifactId());
}
private List extractMavenDependenciesFromFile(InputStream inputStream)
throws IOException {
List dependenciesFromFile = new ArrayList();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, Charsets.UTF_8));
for (String line; (line = reader.readLine()) != null; ) {
if (lineWithDependencyInfo(line)) {
dependenciesFromFile.add(extractDependencyFromLine(line.trim()));
}
}
return dependenciesFromFile;
}
private DependencyInfo extractDependencyFromLine(String line) {
String[] split = DEPENDENCY_SPLIT_REGEX.split(line);
if (split.length == 6) { // case for i.e.: com.github.jnr:jffi:jar:native:1.2.16:compile
return new DependencyInfo(split[0], split[1], split[4], checkIsOptional(split[5]));
} else { // case for normal: org.ow2.asm:asm:jar:5.0.3:compile
return new DependencyInfo(split[0], split[1], split[3], checkIsOptional(split[4]));
}
}
private boolean checkIsOptional(String scope) {
return scope.contains("(optional)");
}
private boolean lineWithDependencyInfo(String line) {
return (!line.equals(MAVEN_IGNORE_LINE) && !line.isEmpty());
}
private CPUS getCpuInfo() {
int numberOfProcessors = Runtime.getRuntime().availableProcessors();
String model = Native.isPlatformAvailable() ? Native.getCPU() : UNKNOWN;
return new CPUS(numberOfProcessors, model);
}
private OS getOsInfo() {
String osName = System.getProperty("os.name");
String osVersion = System.getProperty("os.version");
String osArch = System.getProperty("os.arch");
return new OS(osName, osVersion, osArch);
}
static class DependencyInfo {
private final String groupId;
private final String artifactId;
private final String version;
private boolean optional;
DependencyInfo(String groupId, String artifactId, String version, boolean optional) {
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
this.optional = optional;
}
String getGroupId() {
return groupId;
}
String getArtifactId() {
return artifactId;
}
String getVersion() {
return version;
}
boolean isOptional() {
return optional;
}
@Override
public boolean equals(Object other) {
if (other == null || other.getClass() != this.getClass()) return false;
DependencyInfo that = (DependencyInfo) other;
return MoreObjects.equal(groupId, that.groupId)
&& MoreObjects.equal(artifactId, that.artifactId)
&& MoreObjects.equal(version, that.version)
&& MoreObjects.equal(optional, that.optional);
}
@Override
public int hashCode() {
return MoreObjects.hashCode(groupId, artifactId, version, optional);
}
@Override
public String toString() {
return "DependencyInfo{"
+ "groupId='"
+ groupId
+ '\''
+ ", artifactId='"
+ artifactId
+ '\''
+ ", version='"
+ version
+ '\''
+ ", optional="
+ optional
+ '}';
}
}
}