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:
parent
16afbf91bb
commit
488944f4a1
|
@ -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,26 +87,34 @@ 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())) {
|
||||
Manifest manifest = jar.getManifest();
|
||||
hash = manifest.getMainAttributes().getValue("Change");
|
||||
ver = manifest.getMainAttributes().getValue("X-Compile-Elasticsearch-Version");
|
||||
byte[] vers = from(ver);
|
||||
maj = vers[0];
|
||||
min = vers[1];
|
||||
rev = vers[2];
|
||||
|
||||
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");
|
||||
byte[] vers = from(ver);
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue