Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fail plugins on version mismatch #12221

Merged
merged 1 commit into from Jul 14, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
49 changes: 31 additions & 18 deletions core/src/main/java/org/elasticsearch/bootstrap/JarHell.java
Expand Up @@ -19,6 +19,7 @@

package org.elasticsearch.bootstrap;

import org.elasticsearch.Version;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.logging.ESLogger;
Expand All @@ -27,7 +28,6 @@
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
Expand Down Expand Up @@ -99,23 +99,7 @@ public static void checkJarHell(URL urls[]) throws Exception {
try (JarFile file = new JarFile(path.toString())) {
Manifest manifest = file.getManifest();
if (manifest != null) {
// inspect Manifest: give a nice error if jar requires a newer java version
String systemVersion = System.getProperty("java.specification.version");
String targetVersion = manifest.getMainAttributes().getValue("X-Compile-Target-JDK");
if (targetVersion != null) {
float current = Float.POSITIVE_INFINITY;
float target = Float.NEGATIVE_INFINITY;
try {
current = Float.parseFloat(systemVersion);
target = Float.parseFloat(targetVersion);
} catch (NumberFormatException e) {
// some spec changed, time for a more complex parser
}
if (current < target) {
throw new IllegalStateException(path + " requires Java " + targetVersion
+ ", your system: " + systemVersion);
}
}
checkManifest(manifest, path);
}
// inspect entries
Enumeration<JarEntry> elements = file.entries();
Expand Down Expand Up @@ -149,6 +133,35 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
}
}

/** inspect manifest for sure incompatibilities */
static void checkManifest(Manifest manifest, Path jar) {
// give a nice error if jar requires a newer java version
String systemVersion = System.getProperty("java.specification.version");
String targetVersion = manifest.getMainAttributes().getValue("X-Compile-Target-JDK");
if (targetVersion != null) {
float current = Float.POSITIVE_INFINITY;
float target = Float.NEGATIVE_INFINITY;
try {
current = Float.parseFloat(systemVersion);
target = Float.parseFloat(targetVersion);
} catch (NumberFormatException e) {
// some spec changed, time for a more complex parser
}
if (current < target) {
throw new IllegalStateException(jar + " requires Java " + targetVersion
+ ", your system: " + systemVersion);
}
}

// give a nice error if jar is compiled against different es version
String systemESVersion = Version.CURRENT.toString();
String targetESVersion = manifest.getMainAttributes().getValue("X-Compile-Elasticsearch-Version");
if (targetESVersion != null && targetESVersion.equals(systemESVersion) == false) {
throw new IllegalStateException(jar + " requires Elasticsearch " + targetESVersion
+ ", your system: " + systemESVersion);
}
}

static void checkClass(Map<String,Path> clazzes, String clazz, Path jarpath) {
Path previous = clazzes.put(clazz, jarpath);
if (previous != null) {
Expand Down
55 changes: 47 additions & 8 deletions core/src/test/java/org/elasticsearch/bootstrap/JarHellTests.java
Expand Up @@ -19,10 +19,9 @@

package org.elasticsearch.bootstrap;

import org.elasticsearch.Version;
import org.elasticsearch.test.ElasticsearchTestCase;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
Expand Down Expand Up @@ -54,14 +53,15 @@ URL makeJar(Path dir, String name, Manifest manifest, String... files) throws IO
URL makeFile(Path dir, String name) throws IOException {
Path filepath = dir.resolve(name);
Files.newOutputStream(filepath, StandardOpenOption.CREATE).close();
return filepath.toUri().toURL();
return dir.toUri().toURL();
}

public void testDifferentJars() throws Exception {
Path dir = createTempDir();
URL[] jars = {makeJar(dir, "foo.jar", null, "DuplicateClass.class"), makeJar(dir, "bar.jar", null, "DuplicateClass.class")};
try {
JarHell.checkJarHell(jars);
fail("did not get expected exception");
} catch (IllegalStateException e) {
assertTrue(e.getMessage().contains("jar hell!"));
assertTrue(e.getMessage().contains("DuplicateClass"));
Expand Down Expand Up @@ -95,6 +95,7 @@ public void testDirsOnClasspath() throws Exception {
URL[] dirs = {makeFile(dir1, "DuplicateClass.class"), makeFile(dir2, "DuplicateClass.class")};
try {
JarHell.checkJarHell(dirs);
fail("did not get expected exception");
} catch (IllegalStateException e) {
assertTrue(e.getMessage().contains("jar hell!"));
assertTrue(e.getMessage().contains("DuplicateClass"));
Expand All @@ -109,6 +110,7 @@ public void testDirAndJar() throws Exception {
URL[] dirs = {makeJar(dir1, "foo.jar", null, "DuplicateClass.class"), makeFile(dir2, "DuplicateClass.class")};
try {
JarHell.checkJarHell(dirs);
fail("did not get expected exception");
} catch (IllegalStateException e) {
assertTrue(e.getMessage().contains("jar hell!"));
assertTrue(e.getMessage().contains("DuplicateClass"));
Expand All @@ -135,6 +137,7 @@ public void testWithinSingleJar() throws Exception {
URL[] jars = {JarHellTests.class.getResource("duplicate-classes.jar")};
try {
JarHell.checkJarHell(jars);
fail("did not get expected exception");
} catch (IllegalStateException e) {
assertTrue(e.getMessage().contains("jar hell!"));
assertTrue(e.getMessage().contains("DuplicateClass"));
Expand All @@ -154,12 +157,15 @@ public void testRequiredJDKVersionTooOld() throws Exception {
System.setProperty("java.specification.version", "1.7");

Manifest manifest = new Manifest();
manifest.getMainAttributes().put(new Attributes.Name("X-Compile-Target-JDK"), "1.8");
Attributes attributes = manifest.getMainAttributes();
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attributes.put(new Attributes.Name("X-Compile-Target-JDK"), "1.8");
URL[] jars = {makeJar(dir, "foo.jar", manifest, "Foo.class")};
try {
JarHell.checkJarHell(jars);
fail("did not get expected exception");
} catch (IllegalStateException e) {
assertTrue(e.getMessage().contains("requires java 1.8"));
assertTrue(e.getMessage().contains("requires Java 1.8"));
assertTrue(e.getMessage().contains("your system: 1.7"));
} finally {
System.setProperty("java.specification.version", previousJavaVersion);
Expand All @@ -172,7 +178,9 @@ public void testRequiredJDKVersionIsOK() throws Exception {
System.setProperty("java.specification.version", "1.7");

Manifest manifest = new Manifest();
manifest.getMainAttributes().put(new Attributes.Name("X-Compile-Target-JDK"), "1.7");
Attributes attributes = manifest.getMainAttributes();
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attributes.put(new Attributes.Name("X-Compile-Target-JDK"), "1.7");
URL[] jars = {makeJar(dir, "foo.jar", manifest, "Foo.class")};
try {
JarHell.checkJarHell(jars);
Expand All @@ -187,7 +195,9 @@ public void testBadJDKVersionProperty() throws Exception {
System.setProperty("java.specification.version", "bogus");

Manifest manifest = new Manifest();
manifest.getMainAttributes().put(new Attributes.Name("X-Compile-Target-JDK"), "1.7");
Attributes attributes = manifest.getMainAttributes();
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attributes.put(new Attributes.Name("X-Compile-Target-JDK"), "1.7");
URL[] jars = {makeJar(dir, "foo.jar", manifest, "Foo.class")};
try {
JarHell.checkJarHell(jars);
Expand All @@ -199,8 +209,37 @@ public void testBadJDKVersionProperty() throws Exception {
public void testBadJDKVersionInJar() throws Exception {
Path dir = createTempDir();
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(new Attributes.Name("X-Compile-Target-JDK"), "bogus");
Attributes attributes = manifest.getMainAttributes();
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attributes.put(new Attributes.Name("X-Compile-Target-JDK"), "bogus");
URL[] jars = {makeJar(dir, "foo.jar", manifest, "Foo.class")};
JarHell.checkJarHell(jars);
}

/** make sure if a plugin is compiled against the same ES version, it works */
public void testGoodESVersionInJar() throws Exception {
Path dir = createTempDir();
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attributes.put(new Attributes.Name("X-Compile-Elasticsearch-Version"), Version.CURRENT.toString());
URL[] jars = {makeJar(dir, "foo.jar", manifest, "Foo.class")};
JarHell.checkJarHell(jars);
}

/** make sure if a plugin is compiled against a different ES version, it fails */
public void testBadESVersionInJar() throws Exception {
Path dir = createTempDir();
Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes();
attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attributes.put(new Attributes.Name("X-Compile-Elasticsearch-Version"), "1.0-bogus");
URL[] jars = {makeJar(dir, "foo.jar", manifest, "Foo.class")};
try {
JarHell.checkJarHell(jars);
fail("did not get expected exception");
} catch (IllegalStateException e) {
assertTrue(e.getMessage().contains("requires Elasticsearch 1.0-bogus"));
}
}
}