SQL: Handle uberjar scenario where the ES jdbc driver file is bundled in another jar (#51856) (#52024)

(cherry picked from commit 6247b0793c9db19a8a9fa6f0164cc14d0debed6e)
This commit is contained in:
Andrei Stefan 2020-02-07 04:15:59 +02:00 committed by GitHub
parent 16afbf91bb
commit 488944f4a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 13 deletions

View File

@ -7,6 +7,7 @@ package org.elasticsearch.xpack.sql.client;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashSet;
@ -86,14 +87,21 @@ public class Version {
// This is similar to how Elasticsearch's Build class digs up its build information.
// Since version info is not critical, the parsing is lenient
URL url = Version.class.getProtectionDomain().getCodeSource().getLocation();
String urlStr = url.toString();
CURRENT = extractVersion(url);
}
static Version extractVersion(URL url) {
String urlStr = url.toString();
byte maj = 0, min = 0, rev = 0;
String ver = "Unknown";
String hash = ver;
if (urlStr.endsWith(".jar")) {
try (JarInputStream jar = new JarInputStream(url.openStream())) {
if (urlStr.endsWith(".jar") || urlStr.endsWith(".jar!/")) {
try {
URLConnection conn = url.openConnection();
conn.setUseCaches(false);
try (JarInputStream jar = new JarInputStream(conn.getInputStream())) {
Manifest manifest = jar.getManifest();
hash = manifest.getMainAttributes().getValue("Change");
ver = manifest.getMainAttributes().getValue("X-Compile-Elasticsearch-Version");
@ -101,11 +109,12 @@ public class Version {
maj = vers[0];
min = vers[1];
rev = vers[2];
}
} catch (Exception ex) {
throw new IllegalArgumentException("Detected Elasticsearch JDBC jar but cannot retrieve its version", ex);
}
}
CURRENT = new Version(ver, hash, maj, min, rev);
return new Version(ver, hash, maj, min, rev);
}
@Override

View File

@ -6,7 +6,17 @@
package org.elasticsearch.xpack.sql.client;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.sql.client.Version;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
public class VersionTests extends ESTestCase {
public void test70Version() {
@ -43,4 +53,47 @@ public class VersionTests extends ESTestCase {
IllegalArgumentException err = expectThrows(IllegalArgumentException.class, () -> Version.from("7.1"));
assertEquals("Invalid version 7.1", err.getMessage());
}
public void testVersionFromJarInJar() throws IOException {
final String JDBC_JAR_NAME = "es-sql-jdbc.jar";
final String JAR_PATH_SEPARATOR = "!/";
Path dir = createTempDir();
Path jarPath = dir.resolve("uberjar.jar"); // simulated uberjar containing the jdbc driver
Path innerJarPath = dir.resolve(JDBC_JAR_NAME); // simulated ES JDBC driver file
Manifest jdbcJarManifest = new Manifest();
Attributes attributes = jdbcJarManifest.getMainAttributes();
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attributes.put(new Attributes.Name("Change"), "abc");
attributes.put(new Attributes.Name("X-Compile-Elasticsearch-Version"), "1.2.3");
// create the jdbc driver file
try (JarOutputStream jdbc = new JarOutputStream(Files.newOutputStream(innerJarPath, StandardOpenOption.CREATE), jdbcJarManifest)) {}
// create the uberjar and embed the jdbc driver one into it
try (BufferedInputStream in = new BufferedInputStream(Files.newInputStream(innerJarPath));
JarOutputStream out = new JarOutputStream(Files.newOutputStream(jarPath, StandardOpenOption.CREATE), new Manifest())) {
JarEntry entry = new JarEntry(JDBC_JAR_NAME + JAR_PATH_SEPARATOR);
out.putNextEntry(entry);
byte[] buffer = new byte[1024];
while (true) {
int count = in.read(buffer);
if (count == -1) {
break;
}
out.write(buffer, 0, count);
}
}
URL jarInJar = new URL("jar:" + jarPath.toUri().toURL().toString() + JAR_PATH_SEPARATOR + JDBC_JAR_NAME + JAR_PATH_SEPARATOR);
Version version = Version.extractVersion(jarInJar);
assertEquals(1, version.major);
assertEquals(2, version.minor);
assertEquals(3, version.revision);
assertEquals("abc", version.hash);
assertEquals("1.2.3", version.version);
}
}