Consistently name Groovy scripts with the same content

When adding a script to the Groovy classloader, the script name is used
as the class identifier in the classloader. This means that in order not
to break JVM Classloader convention, that script must always be
available by that name. As a result, modifying a script with the same
content over and over causes it to be loaded with a different name (due
to the incrementing integer).

This is particularly bad when something like chef or puppet replaces the
on-disk script file with the same content over and over every time a
machine is converged.

This change makes the script name the SHA1 hash of the script itself,
meaning that replacing a script with the same text will use the same
script name.

Resolves #12212
This commit is contained in:
Lee Hinman 2015-07-16 12:43:30 -06:00
parent c315d54c2a
commit d902012835

View File

@ -19,6 +19,8 @@
package org.elasticsearch.script.groovy;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import groovy.lang.Binding;
import groovy.lang.GroovyClassLoader;
import groovy.lang.Script;
@ -49,7 +51,6 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
/**
* Provides the infrastructure for Groovy as a scripting language for Elasticsearch
@ -57,7 +58,6 @@ import java.util.concurrent.atomic.AtomicLong;
public class GroovyScriptEngineService extends AbstractComponent implements ScriptEngineService {
public static final String NAME = "groovy";
private final AtomicLong counter = new AtomicLong();
private final GroovyClassLoader loader;
@Inject
@ -111,7 +111,7 @@ public class GroovyScriptEngineService extends AbstractComponent implements Scri
@Override
public Object compile(String script) {
try {
return loader.parseClass(script, generateScriptName());
return loader.parseClass(script, Hashing.sha1().hashString(script, Charsets.UTF_8).toString());
} catch (Throwable e) {
if (logger.isTraceEnabled()) {
logger.trace("exception compiling Groovy script:", e);
@ -190,10 +190,6 @@ public class GroovyScriptEngineService extends AbstractComponent implements Scri
return value;
}
private String generateScriptName() {
return "Script" + counter.incrementAndGet() + ".groovy";
}
public static final class GroovyScript implements ExecutableScript, LeafSearchScript {
private final CompiledScript compiledScript;