Merge pull request #12424 from rmuir/plugin_java_version

make java.version mandatory for jvm plugins
This commit is contained in:
Robert Muir 2015-07-24 11:37:15 -04:00
commit 219f48119c
5 changed files with 124 additions and 33 deletions

View File

@ -136,21 +136,9 @@ public class JarHell {
/** 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);
}
checkJavaVersion(jar.toString(), targetVersion);
}
// give a nice error if jar is compiled against different es version
@ -162,6 +150,26 @@ public class JarHell {
}
}
/**
* Checks that the java specification version {@code targetVersion}
* required by {@code resource} is compatible with the current installation.
*/
public static void checkJavaVersion(String resource, String targetVersion) {
String systemVersion = System.getProperty("java.specification.version");
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(resource + " requires Java " + targetVersion
+ ", your system: " + systemVersion);
}
}
static void checkClass(Map<String,Path> clazzes, String clazz, Path jarpath) {
Path previous = clazzes.put(clazz, jarpath);
if (previous != null) {

View File

@ -19,6 +19,7 @@
package org.elasticsearch.plugins;
import org.elasticsearch.Version;
import org.elasticsearch.bootstrap.JarHell;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Streamable;
@ -110,6 +111,11 @@ public class PluginInfo implements Streamable, ToXContent {
if (esVersion.equals(Version.CURRENT) == false) {
throw new IllegalArgumentException("Elasticsearch version [" + esVersionString + "] is too old for plugin [" + name + "]");
}
String javaVersionString = props.getProperty("java.version");
if (javaVersionString == null) {
throw new IllegalArgumentException("Property [java.version] is missing for jvm plugin [" + name + "]");
}
JarHell.checkJavaVersion(name, javaVersionString);
isolated = Boolean.parseBoolean(props.getProperty("isolated", "true"));
classname = props.getProperty("classname");
if (classname == null) {

View File

@ -57,6 +57,7 @@ public class PluginInfoTests extends ElasticsearchTestCase {
"description", "fake desc",
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"jvm", "true",
"classname", "FakePlugin");
PluginInfo info = PluginInfo.readFromProperties(pluginDir);
@ -119,6 +120,38 @@ public class PluginInfoTests extends ElasticsearchTestCase {
}
}
public void testReadFromPropertiesJavaVersionMissing() throws Exception {
Path pluginDir = createTempDir().resolve("fake-plugin");
writeProperties(pluginDir,
"description", "fake desc",
"elasticsearch.version", Version.CURRENT.toString(),
"version", "1.0",
"jvm", "true");
try {
PluginInfo.readFromProperties(pluginDir);
fail("expected missing java version exception");
} catch (IllegalArgumentException e) {
assertTrue(e.getMessage().contains("[java.version] is missing"));
}
}
public void testReadFromPropertiesJavaVersionIncompatible() throws Exception {
Path pluginDir = createTempDir().resolve("fake-plugin");
writeProperties(pluginDir,
"description", "fake desc",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", "1000000.0",
"classname", "FakePlugin",
"version", "1.0",
"jvm", "true");
try {
PluginInfo.readFromProperties(pluginDir);
fail("expected incompatible java version exception");
} catch (IllegalStateException e) {
assertTrue(e.getMessage(), e.getMessage().contains("fake-plugin requires Java"));
}
}
public void testReadFromPropertiesBogusElasticsearchVersion() throws Exception {
Path pluginDir = createTempDir().resolve("fake-plugin");
writeProperties(pluginDir,
@ -155,6 +188,7 @@ public class PluginInfoTests extends ElasticsearchTestCase {
"description", "fake desc",
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"jvm", "true");
try {
PluginInfo.readFromProperties(pluginDir);
@ -170,7 +204,6 @@ public class PluginInfoTests extends ElasticsearchTestCase {
writeProperties(pluginDir,
"description", "fake desc",
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"site", "true");
PluginInfo info = PluginInfo.readFromProperties(pluginDir);
assertTrue(info.isSite());
@ -183,7 +216,6 @@ public class PluginInfoTests extends ElasticsearchTestCase {
writeProperties(pluginDir,
"description", "fake desc",
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"site", "true");
try {
PluginInfo.readFromProperties(pluginDir);

View File

@ -131,6 +131,7 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
"description", "fake desc",
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"jvm", "true",
"classname", "FakePlugin");
@ -175,6 +176,7 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
"description", "fake desc",
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"jvm", "true",
"classname", "FakePlugin");
@ -210,6 +212,7 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
"description", "fake desc",
"version", "2.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"jvm", "true",
"classname", "FakePlugin");
@ -245,6 +248,7 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
"description", "fake desc",
"version", "3.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"jvm", "true",
"classname", "FakePlugin");
@ -272,6 +276,7 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
"description", "fake desc",
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"jvm", "true",
"classname", "FakePlugin");
@ -305,6 +310,7 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
"description", "fake desc",
"version", "1.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"jvm", "true",
"classname", "FakePlugin");
assertStatusOk(String.format(Locale.ROOT, "install %s --url %s --verbose", pluginName, pluginUrl));
@ -412,6 +418,7 @@ public class PluginManagerTests extends ElasticsearchIntegrationTest {
"description", "fake desc",
"version", "1.0.0",
"elasticsearch.version", Version.CURRENT.toString(),
"java.version", System.getProperty("java.specification.version"),
"jvm", "true",
"classname", "FakePlugin");

View File

@ -1,32 +1,70 @@
# elasticsearch plugin descriptor file
# Elasticsearch plugin descriptor file
# This file must exist as 'plugin-descriptor.properties' at
# the root directory of all plugins.
#
# A plugin can be 'site', 'jvm', or both.
#
### example site plugin for "foo":
#
# foo.zip <-- zip file for the plugin, with this structure:
# _site/ <-- the contents that will be served
# plugin-descriptor.properties <-- example contents below:
#
# site=true
# description=My cool plugin
# version=1.0
#
### example jvm plugin for "foo"
#
# foo.zip <-- zip file for the plugin, with this structure:
# <arbitrary name1>.jar <-- classes, resources, dependencies
# <arbitrary nameN>.jar <-- any number of jars
# plugin-descriptor.properties <-- example contents below:
#
# example:
# jvm=true
# classname=foo.bar.BazPlugin
# isolated=true
# site=false
# description=My cool plugin
# version=2.0
# elasticsearch.version=2.0
# java.version=1.7
#
# A plugin can be 'jvm', 'site', or both
#
# 'jvm': true if the 'classname' class should be loaded
# from jar files in the root directory of the plugin
jvm=${elasticsearch.plugin.jvm}
# 'classname': the name of the class to load.
classname=${elasticsearch.plugin.classname}
# 'isolated': true if the plugin should have its own classloader.
# passing false is deprecated, and only intended to support plugins
# that have hard dependencies against each other
isolated=${elasticsearch.plugin.isolated}
#
# 'site': true if the contents of _site should be served
site=${elasticsearch.plugin.site}
### mandatory elements for all plugins:
#
# 'description': simple summary of the plugin
description=${project.description}
#
# 'version': plugin's version
version=${project.version}
#
### mandatory elements for site plugins:
#
# 'site': set to true to indicate contents of the _site/
# directory in the root of the plugin should be served.
site=${elasticsearch.plugin.site}
#
### mandatory elements for jvm plugins :
#
# 'jvm': true if the 'classname' class should be loaded
# from jar files in the root directory of the plugin.
# Note that only jar files in the root directory are
# added to the classpath for the plugin! If you need
# other resources, package them into a resources jar.
jvm=${elasticsearch.plugin.jvm}
#
# 'classname': the name of the class to load, fully-qualified.
classname=${elasticsearch.plugin.classname}
#
# 'java.version' version of java the code is built against
java.version=${maven.compiler.target}
#
# 'elasticsearch.version' version of elasticsearch compiled against
elasticsearch.version=${elasticsearch.version}
#
### deprecated elements for jvm plugins :
#
# 'isolated': true if the plugin should have its own classloader.
# passing false is deprecated, and only intended to support plugins
# that have hard dependencies against each other. If this is
# not specified, then the plugin is isolated by default.
isolated=${elasticsearch.plugin.isolated}
#