Browse Source

Scripting: Remove native scripts (#24726)

Native scripts have been replaced in documentation by implementing
a ScriptEngine and they were deprecated in 5.5.0. This commit
removes the native script infrastructure for 6.0.

closes #19966
Ryan Ernst 8 years ago
parent
commit
26e2e933f5
31 changed files with 267 additions and 1446 deletions
  1. 0 11
      core/src/main/java/org/elasticsearch/plugins/ScriptPlugin.java
  2. 0 40
      core/src/main/java/org/elasticsearch/script/AbstractDoubleSearchScript.java
  3. 0 27
      core/src/main/java/org/elasticsearch/script/AbstractExecutableScript.java
  4. 0 40
      core/src/main/java/org/elasticsearch/script/AbstractLongSearchScript.java
  5. 0 124
      core/src/main/java/org/elasticsearch/script/AbstractSearchScript.java
  6. 0 100
      core/src/main/java/org/elasticsearch/script/NativeScriptEngine.java
  7. 0 57
      core/src/main/java/org/elasticsearch/script/NativeScriptFactory.java
  8. 0 5
      core/src/main/java/org/elasticsearch/script/ScriptModes.java
  9. 0 4
      core/src/main/java/org/elasticsearch/script/ScriptModule.java
  10. 0 4
      core/src/main/java/org/elasticsearch/script/ScriptSettings.java
  11. 1 12
      core/src/test/java/org/elasticsearch/common/lucene/search/function/ScriptScoreFunctionTests.java
  12. 12 41
      core/src/test/java/org/elasticsearch/index/WaitUntilRefreshIT.java
  13. 0 111
      core/src/test/java/org/elasticsearch/script/NativeScriptTests.java
  14. 0 184
      core/src/test/java/org/elasticsearch/script/ScriptFieldIT.java
  15. 1 11
      core/src/test/java/org/elasticsearch/script/ScriptModesTests.java
  16. 21 53
      core/src/test/java/org/elasticsearch/search/SearchCancellationIT.java
  17. 15 43
      core/src/test/java/org/elasticsearch/search/SearchTimeoutIT.java
  18. 11 10
      core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateHistogramIT.java
  19. 7 8
      core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateRangeIT.java
  20. 0 130
      core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateScriptMocks.java
  21. 56 0
      core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateScriptMocksPlugin.java
  22. 17 49
      core/src/test/java/org/elasticsearch/search/aggregations/bucket/IpRangeIT.java
  23. 21 10
      core/src/test/java/org/elasticsearch/search/aggregations/bucket/SignificantTermsSignificanceScoreIT.java
  24. 78 35
      core/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptIT.java
  25. 0 35
      core/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptPlugin.java
  26. 0 117
      core/src/test/java/org/elasticsearch/update/UpdateByNativeScriptIT.java
  27. 5 0
      docs/reference/migration/migrate_6_0/scripting.asciidoc
  28. 22 5
      test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java
  29. 0 58
      test/framework/src/main/java/org/elasticsearch/search/aggregations/bucket/script/NativeSignificanceScoreScriptNoParams.java
  30. 0 63
      test/framework/src/main/java/org/elasticsearch/search/aggregations/bucket/script/NativeSignificanceScoreScriptWithParams.java
  31. 0 59
      test/framework/src/main/java/org/elasticsearch/search/aggregations/bucket/script/TestScript.java

+ 0 - 11
core/src/main/java/org/elasticsearch/plugins/ScriptPlugin.java

@@ -19,13 +19,9 @@
 package org.elasticsearch.plugins;
 
 import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.script.NativeScriptFactory;
 import org.elasticsearch.script.ScriptContext;
 import org.elasticsearch.script.ScriptEngine;
 
-import java.util.Collections;
-import java.util.List;
-
 /**
  * An additional extension point for {@link Plugin}s that extends Elasticsearch's scripting functionality.
  */
@@ -38,13 +34,6 @@ public interface ScriptPlugin {
         return null;
     }
 
-    /**
-     * Returns a list of {@link NativeScriptFactory} instances.
-     */
-    default List<NativeScriptFactory> getNativeScripts() {
-        return Collections.emptyList();
-    }
-
     /**
      * Returns a {@link ScriptContext.Plugin} instance or <code>null</code> if this plugin doesn't add a new script context plugin
      */

+ 0 - 40
core/src/main/java/org/elasticsearch/script/AbstractDoubleSearchScript.java

@@ -1,40 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.script;
-
-/**
- * A simpler base class instead of {@link AbstractSearchScript} for computations
- * that return a double number.
- */
-public abstract class AbstractDoubleSearchScript extends AbstractSearchScript {
-
-    @Override
-    public Object run() {
-        return runAsDouble();
-    }
-
-    @Override
-    public abstract double runAsDouble();
-
-    @Override
-    public long runAsLong() {
-        return (long) runAsDouble();
-    }
-}

+ 0 - 27
core/src/main/java/org/elasticsearch/script/AbstractExecutableScript.java

@@ -1,27 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.script;
-
-public abstract class AbstractExecutableScript implements ExecutableScript {
-
-    @Override
-    public void setNextVar(String name, Object value) {
-    }
-}

+ 0 - 40
core/src/main/java/org/elasticsearch/script/AbstractLongSearchScript.java

@@ -1,40 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.script;
-
-/**
- * A simpler base class instead of {@link AbstractSearchScript} for computations
- * that return a long number.
- */
-public abstract class AbstractLongSearchScript extends AbstractSearchScript {
-
-    @Override
-    public Object run() {
-        return runAsLong();
-    }
-
-    @Override
-    public abstract long runAsLong();
-
-    @Override
-    public double runAsDouble() {
-        return runAsLong();
-    }
-}

+ 0 - 124
core/src/main/java/org/elasticsearch/script/AbstractSearchScript.java

@@ -1,124 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.script;
-
-import org.apache.lucene.search.Scorer;
-import org.elasticsearch.index.fielddata.ScriptDocValues;
-import org.elasticsearch.search.lookup.LeafDocLookup;
-import org.elasticsearch.search.lookup.LeafFieldsLookup;
-import org.elasticsearch.search.lookup.LeafSearchLookup;
-import org.elasticsearch.search.lookup.SourceLookup;
-
-import java.io.IOException;
-import java.util.Map;
-
-/**
- * A base class for any script type that is used during the search process (custom score, aggs, and so on).
- * <p>
- * If the script returns a specific numeric type, consider overriding the type specific base classes
- * such as {@link AbstractDoubleSearchScript} and {@link AbstractLongSearchScript}
- * for better performance.
- * <p>
- * The use is required to implement the {@link #run()} method.
- */
-public abstract class AbstractSearchScript extends AbstractExecutableScript implements LeafSearchScript {
-
-    private LeafSearchLookup lookup;
-    private Scorer scorer;
-
-    /**
-     * Returns the doc lookup allowing to access field data (cached) values as well as the current document score
-     * (where applicable).
-     */
-    protected final LeafDocLookup doc() {
-        return lookup.doc();
-    }
-
-    /**
-     * Returns the current score and only applicable when used as a scoring script in a custom score query!.
-     */
-    protected final float score() throws IOException {
-        return scorer.score();
-    }
-
-    /**
-     * Returns field data strings access for the provided field.
-     */
-    protected ScriptDocValues.Strings docFieldStrings(String field) {
-        return (ScriptDocValues.Strings) doc().get(field);
-    }
-
-    /**
-     * Returns field data double (floating point) access for the provided field.
-     */
-    protected ScriptDocValues.Doubles docFieldDoubles(String field) {
-        return (ScriptDocValues.Doubles) doc().get(field);
-    }
-
-    /**
-     * Returns field data long (integers) access for the provided field.
-     */
-    protected ScriptDocValues.Longs docFieldLongs(String field) {
-        return (ScriptDocValues.Longs) doc().get(field);
-    }
-
-    /**
-     * Allows to access the actual source (loaded and parsed).
-     */
-    protected final SourceLookup source() {
-        return lookup.source();
-    }
-
-    /**
-     * Allows to access the *stored* fields.
-     */
-    protected final LeafFieldsLookup fields() {
-        return lookup.fields();
-    }
-
-    void setLookup(LeafSearchLookup lookup) {
-        this.lookup = lookup;
-    }
-
-    @Override
-    public void setScorer(Scorer scorer) {
-        this.scorer = scorer;
-    }
-
-    @Override
-    public void setDocument(int doc) {
-        lookup.setDocument(doc);
-    }
-
-    @Override
-    public void setSource(Map<String, Object> source) {
-        lookup.source().setSource(source);
-    }
-
-    @Override
-    public long runAsLong() {
-        return ((Number) run()).longValue();
-    }
-
-    @Override
-    public double runAsDouble() {
-        return ((Number) run()).doubleValue();
-    }
-}

+ 0 - 100
core/src/main/java/org/elasticsearch/script/NativeScriptEngine.java

@@ -1,100 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.script;
-
-import org.apache.logging.log4j.Logger;
-import org.apache.lucene.index.LeafReaderContext;
-import org.elasticsearch.common.Nullable;
-import org.elasticsearch.common.component.AbstractComponent;
-import org.elasticsearch.common.logging.DeprecationLogger;
-import org.elasticsearch.common.logging.Loggers;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.search.lookup.SearchLookup;
-
-import java.io.IOException;
-import java.util.Map;
-
-import static java.util.Collections.unmodifiableMap;
-
-/**
- * A native script engine service.
- */
-public class NativeScriptEngine extends AbstractComponent implements ScriptEngine {
-
-    public static final String NAME = "native";
-
-    private final Map<String, NativeScriptFactory> scripts;
-
-    public NativeScriptEngine(Settings settings, Map<String, NativeScriptFactory> scripts) {
-        super(settings);
-        if (scripts.isEmpty() == false) {
-            Logger logger = Loggers.getLogger(ScriptModule.class);
-            DeprecationLogger deprecationLogger = new DeprecationLogger(logger);
-            deprecationLogger.deprecated("Native scripts are deprecated. Use a custom ScriptEngine to write scripts in java.");
-        }
-        this.scripts = unmodifiableMap(scripts);
-    }
-
-    @Override
-    public String getType() {
-        return NAME;
-    }
-
-    @Override
-    public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
-        NativeScriptFactory scriptFactory = scripts.get(scriptSource);
-        if (scriptFactory != null) {
-            return scriptFactory;
-        }
-        throw new IllegalArgumentException("Native script [" + scriptSource + "] not found");
-    }
-
-    @Override
-    public ExecutableScript executable(CompiledScript compiledScript, @Nullable Map<String, Object> vars) {
-        NativeScriptFactory scriptFactory = (NativeScriptFactory) compiledScript.compiled();
-        return scriptFactory.newScript(vars);
-    }
-
-    @Override
-    public SearchScript search(CompiledScript compiledScript, final SearchLookup lookup, @Nullable final Map<String, Object> vars) {
-        final NativeScriptFactory scriptFactory = (NativeScriptFactory) compiledScript.compiled();
-        final AbstractSearchScript script = (AbstractSearchScript) scriptFactory.newScript(vars);
-        return new SearchScript() {
-            @Override
-            public LeafSearchScript getLeafSearchScript(LeafReaderContext context) throws IOException {
-                script.setLookup(lookup.getLeafSearchLookup(context));
-                return script;
-            }
-            @Override
-            public boolean needsScores() {
-                return scriptFactory.needsScores();
-            }
-        };
-    }
-
-    @Override
-    public void close() {
-    }
-
-    @Override
-    public boolean isInlineScriptEnabled() {
-        return true;
-    }
-}

+ 0 - 57
core/src/main/java/org/elasticsearch/script/NativeScriptFactory.java

@@ -1,57 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.script;
-
-import org.elasticsearch.common.Nullable;
-
-import java.util.Map;
-
-/**
- * A factory to create instances of either {@link ExecutableScript} or {@link SearchScript}. Note,
- * if this factory creates {@link SearchScript}, it must extend {@link AbstractSearchScript}.
- *
- * @see AbstractExecutableScript
- * @see AbstractSearchScript
- * @see AbstractLongSearchScript
- * @see AbstractDoubleSearchScript
- * @deprecated Create a {@link ScriptEngine} instead of using native scripts
- */
-@Deprecated
-public interface NativeScriptFactory {
-
-    /**
-     * Creates a new instance of either a {@link ExecutableScript} or a {@link SearchScript}.
-     *
-     * @param params The parameters passed to the script. Can be <tt>null</tt>.
-     */
-    ExecutableScript newScript(@Nullable Map<String, Object> params);
-
-    /**
-     * Indicates if document scores may be needed by the produced scripts.
-     *
-     * @return {@code true} if scores are needed.
-     */
-    boolean needsScores();
-
-    /**
-     * Returns the name of the script factory
-     */
-    String getName();
-}

+ 0 - 5
core/src/main/java/org/elasticsearch/script/ScriptModes.java

@@ -105,11 +105,6 @@ public class ScriptModes {
      * @return whether scripts are enabled (true) or disabled (false)
      */
     public boolean getScriptEnabled(String lang, ScriptType scriptType, ScriptContext scriptContext) {
-        //native scripts are always enabled as they are static by definition
-        if (NativeScriptEngine.NAME.equals(lang)) {
-            return true;
-        }
-
         if (typesAllowed != null && typesAllowed.contains(scriptType.getName()) == false) {
             throw new IllegalArgumentException("[" + scriptType.getName() + "] scripts cannot be executed");
         }

+ 0 - 4
core/src/main/java/org/elasticsearch/script/ScriptModule.java

@@ -45,12 +45,8 @@ public class ScriptModule {
      * {@link ScriptModule#ScriptModule(Settings, List, List)} for easier use in tests.
      */
     public static ScriptModule create(Settings settings, List<ScriptPlugin> scriptPlugins) {
-        Map<String, NativeScriptFactory> factoryMap = scriptPlugins.stream().flatMap(x -> x.getNativeScripts().stream())
-            .collect(Collectors.toMap(NativeScriptFactory::getName, Function.identity()));
-        NativeScriptEngine nativeScriptEngineService = new NativeScriptEngine(settings, factoryMap);
         List<ScriptEngine> scriptEngines = scriptPlugins.stream().map(x -> x.getScriptEngine(settings))
             .filter(Objects::nonNull).collect(Collectors.toList());
-        scriptEngines.add(nativeScriptEngineService);
         List<ScriptContext.Plugin> plugins = scriptPlugins.stream().map(x -> x.getCustomScriptContexts()).filter(Objects::nonNull)
                 .collect(Collectors.toList());
         return new ScriptModule(settings, scriptEngines, plugins);

+ 0 - 4
core/src/main/java/org/elasticsearch/script/ScriptSettings.java

@@ -74,10 +74,6 @@ public class ScriptSettings {
         final List<Setting<Boolean>> scriptModeSettings = new ArrayList<>();
 
         for (final Class<? extends ScriptEngine> scriptEngineService : scriptEngineRegistry.getRegisteredScriptEngineServices()) {
-            if (scriptEngineService == NativeScriptEngine.class) {
-                // native scripts are always enabled, and their settings can not be changed
-                continue;
-            }
             final String language = scriptEngineRegistry.getLanguage(scriptEngineService);
             for (final ScriptType scriptType : ScriptType.values()) {
                 // Top level, like "script.engine.groovy.inline"

+ 1 - 12
core/src/test/java/org/elasticsearch/common/lucene/search/function/ScriptScoreFunctionTests.java

@@ -20,7 +20,6 @@
 package org.elasticsearch.common.lucene.search.function;
 
 import org.apache.lucene.index.LeafReaderContext;
-import org.elasticsearch.script.AbstractDoubleSearchScript;
 import org.elasticsearch.script.GeneralScriptException;
 import org.elasticsearch.script.LeafSearchScript;
 import org.elasticsearch.script.SearchScript;
@@ -37,17 +36,7 @@ public class ScriptScoreFunctionTests extends ESTestCase {
         ScoreFunction scoreFunction = new ScriptScoreFunction(mockScript("Double.NaN"), new SearchScript() {
             @Override
             public LeafSearchScript getLeafSearchScript(LeafReaderContext context) throws IOException {
-                return new AbstractDoubleSearchScript() {
-                    @Override
-                    public double runAsDouble() {
-                        return Double.NaN;
-                    }
-
-                    @Override
-                    public void setDocument(int doc) {
-                        // do nothing: we are a fake with no lookup
-                    }
-                };
+                return () -> Double.NaN;
             }
             
             @Override

+ 12 - 41
core/src/test/java/org/elasticsearch/index/WaitUntilRefreshIT.java

@@ -31,10 +31,8 @@ import org.elasticsearch.action.update.UpdateResponse;
 import org.elasticsearch.client.Requests;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.plugins.ScriptPlugin;
 import org.elasticsearch.rest.RestStatus;
-import org.elasticsearch.script.ExecutableScript;
-import org.elasticsearch.script.NativeScriptFactory;
+import org.elasticsearch.script.MockScriptPlugin;
 import org.elasticsearch.script.Script;
 import org.elasticsearch.script.ScriptType;
 import org.elasticsearch.test.ESIntegTestCase;
@@ -42,9 +40,9 @@ import org.junit.Before;
 
 import java.util.Collection;
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
+import java.util.function.Function;
 
 import static java.util.Collections.emptyMap;
 import static java.util.Collections.singleton;
@@ -111,7 +109,8 @@ public class WaitUntilRefreshIT extends ESIntegTestCase {
         assertSearchHits(client().prepareSearch("test").setQuery(matchQuery("foo", "cat")).get(), "2");
 
         // Update-becomes-delete with RefreshPolicy.WAIT_UNTIL
-        update = client().prepareUpdate("test", "test", "2").setScript(new Script(ScriptType.INLINE, "native", "delete_plz", emptyMap()))
+        update = client().prepareUpdate("test", "test", "2").setScript(
+            new Script(ScriptType.INLINE, "mockscript", "delete_plz", emptyMap()))
                 .setRefreshPolicy(RefreshPolicy.WAIT_UNTIL).get();
         assertEquals(2, update.getVersion());
         assertFalse("request shouldn't have forced a refresh", update.forcedRefresh());
@@ -171,43 +170,15 @@ public class WaitUntilRefreshIT extends ESIntegTestCase {
         return singleton(DeletePlzPlugin.class);
     }
 
-    public static class DeletePlzPlugin extends Plugin implements ScriptPlugin {
+    public static class DeletePlzPlugin extends MockScriptPlugin {
         @Override
-        public List<NativeScriptFactory> getNativeScripts() {
-            return Collections.singletonList(new DeletePlzFactory());
-        }
-    }
-
-    public static class DeletePlzFactory implements NativeScriptFactory {
-        @Override
-        public ExecutableScript newScript(Map<String, Object> params) {
-            return new ExecutableScript() {
-                private Map<String, Object> ctx;
-
-                @Override
-                @SuppressWarnings("unchecked")  // Elasicsearch convention
-                public void setNextVar(String name, Object value) {
-                    if (name.equals("ctx")) {
-                        ctx = (Map<String, Object>) value;
-                    }
-                }
-
-                @Override
-                public Object run() {
-                    ctx.put("op", "delete");
-                    return null;
-                }
-            };
-        }
-
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return "delete_plz";
+        public Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
+            return Collections.singletonMap("delete_plz", params -> {
+                @SuppressWarnings("unchecked")
+                Map<String, Object> ctx = (Map<String, Object>) params.get("ctx");
+                ctx.put("op", "delete");
+                return null;
+            });
         }
     }
 }

+ 0 - 111
core/src/test/java/org/elasticsearch/script/NativeScriptTests.java

@@ -1,111 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.script;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.elasticsearch.common.Nullable;
-import org.elasticsearch.common.settings.Setting;
-import org.elasticsearch.common.settings.Settings;
-import org.elasticsearch.env.Environment;
-import org.elasticsearch.test.ESTestCase;
-import org.elasticsearch.test.InternalSettingsPlugin;
-import org.elasticsearch.watcher.ResourceWatcherService;
-
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
-import static java.util.Collections.singletonMap;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.notNullValue;
-
-public class NativeScriptTests extends ESTestCase {
-    public void testNativeScript() throws InterruptedException {
-        Settings settings = Settings.builder()
-                .put("node.name", "testNativeScript")
-                .put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
-                .build();
-
-        ScriptModule scriptModule = new ScriptModule(settings,
-                singletonList(new NativeScriptEngine(settings, singletonMap("my", new MyNativeScriptFactory()))), emptyList());
-        List<Setting<?>> scriptSettings = scriptModule.getSettings();
-        scriptSettings.add(InternalSettingsPlugin.VERSION_CREATED);
-
-        Script script = new Script(ScriptType.INLINE, NativeScriptEngine.NAME, "my", Collections.emptyMap());
-        CompiledScript compiledScript = scriptModule.getScriptService().compile(script, ScriptContext.Standard.SEARCH);
-        ExecutableScript executable = scriptModule.getScriptService().executable(compiledScript, script.getParams());
-        assertThat(executable.run().toString(), equalTo("test"));
-        assertWarnings("Native scripts are deprecated. Use a custom ScriptEngine to write scripts in java.");
-    }
-
-    public void testFineGrainedSettingsDontAffectNativeScripts() throws IOException {
-        Settings.Builder builder = Settings.builder();
-        if (randomBoolean()) {
-            ScriptType scriptType = randomFrom(ScriptType.values());
-            builder.put("script" + "." + scriptType.getName(), randomBoolean());
-        } else {
-            ScriptContext scriptContext = randomFrom(ScriptContext.Standard.values());
-            builder.put("script" + "." + scriptContext.getKey(), randomBoolean());
-        }
-        Settings settings = builder.put(Environment.PATH_HOME_SETTING.getKey(), createTempDir()).build();
-        Map<String, NativeScriptFactory> nativeScriptFactoryMap = new HashMap<>();
-        nativeScriptFactoryMap.put("my", new MyNativeScriptFactory());
-        ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singleton(new NativeScriptEngine(settings,
-            nativeScriptFactoryMap)));
-        ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(new ArrayList<>());
-        ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
-        ScriptService scriptService = new ScriptService(settings, scriptEngineRegistry,
-            scriptContextRegistry, scriptSettings);
-
-        for (ScriptContext scriptContext : scriptContextRegistry.scriptContexts()) {
-            assertThat(scriptService.compile(new Script(ScriptType.INLINE, NativeScriptEngine.NAME, "my", Collections.emptyMap()),
-                scriptContext), notNullValue());
-        }
-        assertWarnings("Native scripts are deprecated. Use a custom ScriptEngine to write scripts in java.");
-    }
-
-    public static class MyNativeScriptFactory implements NativeScriptFactory {
-        @Override
-        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
-            return new MyScript();
-        }
-
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return "my";
-        }
-    }
-
-    static class MyScript extends AbstractExecutableScript {
-        @Override
-        public Object run() {
-            return "test";
-        }
-    }
-}

+ 0 - 184
core/src/test/java/org/elasticsearch/script/ScriptFieldIT.java

@@ -1,184 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.script;
-
-import org.elasticsearch.action.search.SearchResponse;
-import org.elasticsearch.common.Nullable;
-import org.elasticsearch.index.query.QueryBuilders;
-import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.plugins.ScriptPlugin;
-import org.elasticsearch.search.SearchHit;
-import org.elasticsearch.test.ESIntegTestCase;
-import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
-import org.elasticsearch.test.ESIntegTestCase.Scope;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-
-import static org.hamcrest.Matchers.equalTo;
-
-@ClusterScope(scope = Scope.SUITE, numDataNodes = 3)
-public class ScriptFieldIT extends ESIntegTestCase {
-
-    @Override
-    protected Collection<Class<? extends Plugin>> nodePlugins() {
-        return Arrays.asList(CustomScriptPlugin.class);
-    }
-
-    static int[] intArray = { Integer.MAX_VALUE, Integer.MIN_VALUE, 3 };
-    static long[] longArray = { Long.MAX_VALUE, Long.MIN_VALUE, 9223372036854775807L };
-    static float[] floatArray = { Float.MAX_VALUE, Float.MIN_VALUE, 3.3f };
-    static double[] doubleArray = { Double.MAX_VALUE, Double.MIN_VALUE, 3.3d };
-
-    public void testNativeScript() throws InterruptedException, ExecutionException {
-
-        indexRandom(true, client().prepareIndex("test", "type1", "1").setSource("text", "doc1"), client()
-                .prepareIndex("test", "type1", "2").setSource("text", "doc2"),
-                client().prepareIndex("test", "type1", "3").setSource("text", "doc3"), client().prepareIndex("test", "type1", "4")
-                        .setSource("text", "doc4"), client().prepareIndex("test", "type1", "5").setSource("text", "doc5"), client()
-                        .prepareIndex("test", "type1", "6").setSource("text", "doc6"));
-
-        client().admin().indices().prepareFlush("test").execute().actionGet();
-        SearchResponse sr = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery())
-                .addScriptField("int", new Script(ScriptType.INLINE, "native", "int", Collections.emptyMap()))
-                .addScriptField("float", new Script(ScriptType.INLINE, "native", "float", Collections.emptyMap()))
-                .addScriptField("double", new Script(ScriptType.INLINE, "native", "double", Collections.emptyMap()))
-                .addScriptField("long", new Script(ScriptType.INLINE, "native", "long", Collections.emptyMap())).execute().actionGet();
-        assertThat(sr.getHits().getHits().length, equalTo(6));
-        for (SearchHit hit : sr.getHits().getHits()) {
-            Object result = hit.getFields().get("int").getValues().get(0);
-            assertThat(result, equalTo((Object) intArray));
-            result = hit.getFields().get("long").getValues().get(0);
-            assertThat(result, equalTo((Object) longArray));
-            result = hit.getFields().get("float").getValues().get(0);
-            assertThat(result, equalTo((Object) floatArray));
-            result = hit.getFields().get("double").getValues().get(0);
-            assertThat(result, equalTo((Object) doubleArray));
-        }
-    }
-
-    public static class IntArrayScriptFactory implements NativeScriptFactory {
-        @Override
-        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
-            return new IntScript();
-        }
-
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return "int";
-        }
-    }
-
-    static class IntScript extends AbstractSearchScript {
-        @Override
-        public Object run() {
-            return intArray;
-        }
-    }
-
-    public static class LongArrayScriptFactory implements NativeScriptFactory {
-        @Override
-        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
-            return new LongScript();
-        }
-
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return "long";
-        }
-    }
-
-    static class LongScript extends AbstractSearchScript {
-        @Override
-        public Object run() {
-            return longArray;
-        }
-    }
-
-    public static class FloatArrayScriptFactory implements NativeScriptFactory {
-        @Override
-        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
-            return new FloatScript();
-        }
-
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return "float";
-        }
-    }
-
-    static class FloatScript extends AbstractSearchScript {
-        @Override
-        public Object run() {
-            return floatArray;
-        }
-    }
-
-    public static class DoubleArrayScriptFactory implements NativeScriptFactory {
-        @Override
-        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
-            return new DoubleScript();
-        }
-
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return "double";
-        }
-    }
-
-    static class DoubleScript extends AbstractSearchScript {
-        @Override
-        public Object run() {
-            return doubleArray;
-        }
-    }
-
-    public static class CustomScriptPlugin extends Plugin implements ScriptPlugin {
-        @Override
-        public List<NativeScriptFactory> getNativeScripts() {
-            return Arrays.asList(new IntArrayScriptFactory(), new LongArrayScriptFactory(), new FloatArrayScriptFactory(),
-                new DoubleArrayScriptFactory());
-        }
-    }
-}

+ 1 - 11
core/src/test/java/org/elasticsearch/script/ScriptModesTests.java

@@ -65,10 +65,7 @@ public class ScriptModesTests extends ESTestCase {
         }
         scriptContextRegistry = new ScriptContextRegistry(contexts.values());
         scriptContexts = scriptContextRegistry.scriptContexts().toArray(new ScriptContext[scriptContextRegistry.scriptContexts().size()]);
-        scriptEngines = buildScriptEnginesByLangMap(newHashSet(
-                //add the native engine just to make sure it gets filtered out
-                new NativeScriptEngine(Settings.EMPTY, Collections.<String, NativeScriptFactory>emptyMap()),
-                new CustomScriptEngine()));
+        scriptEngines = buildScriptEnginesByLangMap(newHashSet(new CustomScriptEngine()));
         ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(scriptEngines.values());
         scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
         checkedSettings = new HashSet<>();
@@ -76,13 +73,6 @@ public class ScriptModesTests extends ESTestCase {
         assertScriptModesNonNull = true;
     }
 
-    @After
-    public void assertNativeScriptsAreAlwaysAllowed() {
-        if (assertScriptModesNonNull) {
-            assertThat(scriptModes.getScriptEnabled(NativeScriptEngine.NAME, randomFrom(ScriptType.values()), randomFrom(scriptContexts)), equalTo(true));
-        }
-    }
-
     @After
     public void assertAllSettingsWereChecked() {
         if (assertScriptModesNonNull) {

+ 21 - 53
core/src/test/java/org/elasticsearch/search/SearchCancellationIT.java

@@ -35,12 +35,10 @@ import org.elasticsearch.common.xcontent.ToXContent;
 import org.elasticsearch.common.xcontent.XContentHelper;
 import org.elasticsearch.plugins.Plugin;
 import org.elasticsearch.plugins.PluginsService;
-import org.elasticsearch.plugins.ScriptPlugin;
-import org.elasticsearch.script.AbstractSearchScript;
-import org.elasticsearch.script.ExecutableScript;
-import org.elasticsearch.script.NativeScriptFactory;
+import org.elasticsearch.script.MockScriptPlugin;
 import org.elasticsearch.script.Script;
 import org.elasticsearch.script.ScriptType;
+import org.elasticsearch.search.lookup.LeafFieldsLookup;
 import org.elasticsearch.tasks.TaskInfo;
 import org.elasticsearch.test.ESIntegTestCase;
 
@@ -51,8 +49,10 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
 
 import static org.elasticsearch.index.query.QueryBuilders.scriptQuery;
+import static org.elasticsearch.search.SearchCancellationIT.ScriptedBlockPlugin.SCRIPT_NAME;
 import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFailures;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.greaterThan;
@@ -93,8 +93,8 @@ public class SearchCancellationIT extends ESIntegTestCase {
             plugins.addAll(pluginsService.filterPlugins(ScriptedBlockPlugin.class));
         }
         for (ScriptedBlockPlugin plugin : plugins) {
-            plugin.scriptedBlockFactory.reset();
-            plugin.scriptedBlockFactory.enableBlock();
+            plugin.reset();
+            plugin.enableBlock();
         }
         return plugins;
     }
@@ -104,7 +104,7 @@ public class SearchCancellationIT extends ESIntegTestCase {
         assertBusy(() -> {
             int numberOfBlockedPlugins = 0;
             for (ScriptedBlockPlugin plugin : plugins) {
-                numberOfBlockedPlugins += plugin.scriptedBlockFactory.hits.get();
+                numberOfBlockedPlugins += plugin.hits.get();
             }
             logger.info("The plugin blocked on {} out of {} shards", numberOfBlockedPlugins, numberOfShards);
             assertThat(numberOfBlockedPlugins, greaterThan(0));
@@ -113,7 +113,7 @@ public class SearchCancellationIT extends ESIntegTestCase {
 
     private void disableBlocks(List<ScriptedBlockPlugin> plugins) throws Exception {
         for (ScriptedBlockPlugin plugin : plugins) {
-            plugin.scriptedBlockFactory.disableBlock();
+            plugin.disableBlock();
         }
     }
 
@@ -148,7 +148,7 @@ public class SearchCancellationIT extends ESIntegTestCase {
         logger.info("Executing search");
         ActionFuture<SearchResponse> searchResponse = client().prepareSearch("test").setQuery(
             scriptQuery(new Script(
-                ScriptType.INLINE, "native", NativeTestScriptedBlockFactory.TEST_NATIVE_BLOCK_SCRIPT, Collections.emptyMap())))
+                ScriptType.INLINE, "mockscript", SCRIPT_NAME, Collections.emptyMap())))
             .execute();
 
         awaitForBlock(plugins);
@@ -166,7 +166,7 @@ public class SearchCancellationIT extends ESIntegTestCase {
         logger.info("Executing search");
         ActionFuture<SearchResponse> searchResponse = client().prepareSearch("test")
             .addScriptField("test_field",
-                new Script(ScriptType.INLINE, "native", NativeTestScriptedBlockFactory.TEST_NATIVE_BLOCK_SCRIPT, Collections.emptyMap())
+                new Script(ScriptType.INLINE, "mockscript", SCRIPT_NAME, Collections.emptyMap())
             ).execute();
 
         awaitForBlock(plugins);
@@ -187,7 +187,7 @@ public class SearchCancellationIT extends ESIntegTestCase {
             .setSize(5)
             .setQuery(
                 scriptQuery(new Script(
-                    ScriptType.INLINE, "native", NativeTestScriptedBlockFactory.TEST_NATIVE_BLOCK_SCRIPT, Collections.emptyMap())))
+                    ScriptType.INLINE, "mockscript", SCRIPT_NAME, Collections.emptyMap())))
             .execute();
 
         awaitForBlock(plugins);
@@ -217,15 +217,15 @@ public class SearchCancellationIT extends ESIntegTestCase {
             .setSize(2)
             .setQuery(
                 scriptQuery(new Script(
-                    ScriptType.INLINE, "native", NativeTestScriptedBlockFactory.TEST_NATIVE_BLOCK_SCRIPT, Collections.emptyMap())))
+                    ScriptType.INLINE, "mockscript", SCRIPT_NAME, Collections.emptyMap())))
             .get();
 
         assertNotNull(searchResponse.getScrollId());
 
         // Enable block so the second request would block
         for (ScriptedBlockPlugin plugin : plugins) {
-            plugin.scriptedBlockFactory.reset();
-            plugin.scriptedBlockFactory.enableBlock();
+            plugin.reset();
+            plugin.enableBlock();
         }
 
         String scrollId = searchResponse.getScrollId();
@@ -247,30 +247,13 @@ public class SearchCancellationIT extends ESIntegTestCase {
     }
 
 
-    public static class ScriptedBlockPlugin extends Plugin implements ScriptPlugin {
-        private NativeTestScriptedBlockFactory scriptedBlockFactory;
-
-        public ScriptedBlockPlugin() {
-            scriptedBlockFactory = new NativeTestScriptedBlockFactory();
-        }
-
-        @Override
-        public List<NativeScriptFactory> getNativeScripts() {
-            return Collections.singletonList(scriptedBlockFactory);
-        }
-    }
-
-    private static class NativeTestScriptedBlockFactory implements NativeScriptFactory {
-
-        public static final String TEST_NATIVE_BLOCK_SCRIPT = "native_test_search_block_script";
+    public static class ScriptedBlockPlugin extends MockScriptPlugin {
+        static final String SCRIPT_NAME = "search_block";
 
         private final AtomicInteger hits = new AtomicInteger();
 
         private final AtomicBoolean shouldBlock = new AtomicBoolean(true);
 
-        NativeTestScriptedBlockFactory() {
-        }
-
         public void reset() {
             hits.set(0);
         }
@@ -284,24 +267,10 @@ public class SearchCancellationIT extends ESIntegTestCase {
         }
 
         @Override
-        public ExecutableScript newScript(Map<String, Object> params) {
-            return new NativeTestScriptedBlock();
-        }
-
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return TEST_NATIVE_BLOCK_SCRIPT;
-        }
-
-        public class NativeTestScriptedBlock extends AbstractSearchScript {
-            @Override
-            public Object run() {
-                Loggers.getLogger(SearchCancellationIT.class).info("Blocking on the document {}", fields().get("_uid"));
+        public Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
+            return Collections.singletonMap(SCRIPT_NAME, params -> {
+                LeafFieldsLookup fieldsLookup = (LeafFieldsLookup) params.get("_fields");
+                Loggers.getLogger(SearchCancellationIT.class).info("Blocking on the document {}", fieldsLookup.get("_uid"));
                 hits.incrementAndGet();
                 try {
                     awaitBusy(() -> shouldBlock.get() == false);
@@ -309,8 +278,7 @@ public class SearchCancellationIT extends ESIntegTestCase {
                     throw new RuntimeException(e);
                 }
                 return true;
-            }
+            });
         }
     }
-
 }

+ 15 - 43
core/src/test/java/org/elasticsearch/search/SearchTimeoutIT.java

@@ -23,22 +23,20 @@ import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.common.unit.TimeValue;
 import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.plugins.ScriptPlugin;
-import org.elasticsearch.script.AbstractSearchScript;
-import org.elasticsearch.script.ExecutableScript;
-import org.elasticsearch.script.NativeScriptFactory;
+import org.elasticsearch.script.MockScriptPlugin;
 import org.elasticsearch.script.Script;
 import org.elasticsearch.script.ScriptType;
 import org.elasticsearch.test.ESIntegTestCase;
 
 import java.util.Collection;
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
 
 import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE;
 import static org.elasticsearch.index.query.QueryBuilders.scriptQuery;
+import static org.elasticsearch.search.SearchTimeoutIT.ScriptedTimeoutPlugin.SCRIPT_NAME;
 import static org.hamcrest.Matchers.equalTo;
 
 @ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.SUITE)
@@ -59,49 +57,23 @@ public class SearchTimeoutIT extends ESIntegTestCase {
 
         SearchResponse searchResponse = client().prepareSearch("test").setTimeout(new TimeValue(10, TimeUnit.MILLISECONDS))
                 .setQuery(scriptQuery(
-                    new Script(ScriptType.INLINE, "native", NativeTestScriptedTimeout.TEST_NATIVE_SCRIPT_TIMEOUT, Collections.emptyMap())))
+                    new Script(ScriptType.INLINE, "mockscript", SCRIPT_NAME, Collections.emptyMap())))
                 .execute().actionGet();
         assertThat(searchResponse.isTimedOut(), equalTo(true));
     }
 
-    public static class ScriptedTimeoutPlugin extends Plugin implements ScriptPlugin {
+    public static class ScriptedTimeoutPlugin extends MockScriptPlugin {
+        static final String SCRIPT_NAME = "search_timeout";
         @Override
-        public List<NativeScriptFactory> getNativeScripts() {
-            return Collections.singletonList(new NativeTestScriptedTimeout.Factory());
+        public Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
+            return Collections.singletonMap(SCRIPT_NAME, params -> {
+                try {
+                    Thread.sleep(500);
+                } catch (InterruptedException e) {
+                    throw new RuntimeException(e);
+                }
+                return true;
+            });
         }
     }
-
-    public static class NativeTestScriptedTimeout extends AbstractSearchScript {
-
-        public static final String TEST_NATIVE_SCRIPT_TIMEOUT = "native_test_search_timeout_script";
-
-        public static class Factory implements NativeScriptFactory {
-
-            @Override
-            public ExecutableScript newScript(Map<String, Object> params) {
-                return new NativeTestScriptedTimeout();
-            }
-
-            @Override
-            public boolean needsScores() {
-                return false;
-            }
-
-            @Override
-            public String getName() {
-                return TEST_NATIVE_SCRIPT_TIMEOUT;
-            }
-        }
-
-        @Override
-        public Object run() {
-            try {
-                Thread.sleep(500);
-            } catch (InterruptedException e) {
-                throw new RuntimeException(e);
-            }
-            return true;
-        }
-    }
-
 }

+ 11 - 10
core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateHistogramIT.java

@@ -34,7 +34,6 @@ import org.elasticsearch.script.Script;
 import org.elasticsearch.script.ScriptType;
 import org.elasticsearch.search.aggregations.AggregationExecutionException;
 import org.elasticsearch.search.aggregations.InternalAggregation;
-import org.elasticsearch.search.aggregations.bucket.DateScriptMocks.DateScriptsMockPlugin;
 import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
 import org.elasticsearch.search.aggregations.bucket.histogram.ExtendedBounds;
 import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
@@ -53,6 +52,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -184,8 +184,7 @@ public class DateHistogramIT extends ESIntegTestCase {
 
     @Override
     protected Collection<Class<? extends Plugin>> nodePlugins() {
-        return Arrays.asList(
-                DateScriptsMockPlugin.class);
+        return Collections.singleton(DateScriptMocksPlugin.class);
     }
 
     @After
@@ -608,7 +607,7 @@ public class DateHistogramIT extends ESIntegTestCase {
         SearchResponse response = client().prepareSearch("idx")
                 .addAggregation(dateHistogram("histo")
                         .field("date")
-                        .script(new Script(ScriptType.INLINE, "native", DateScriptMocks.PlusOneMonthScript.NAME, params))
+                        .script(new Script(ScriptType.INLINE, "mockscript", DateScriptMocksPlugin.LONG_PLUS_ONE_MONTH, params))
                         .dateHistogramInterval(DateHistogramInterval.MONTH)).execute().actionGet();
 
         assertSearchResponse(response);
@@ -747,7 +746,7 @@ public class DateHistogramIT extends ESIntegTestCase {
         SearchResponse response = client().prepareSearch("idx")
                 .addAggregation(dateHistogram("histo")
                         .field("dates")
-                        .script(new Script(ScriptType.INLINE, "native", DateScriptMocks.PlusOneMonthScript.NAME, params))
+                        .script(new Script(ScriptType.INLINE, "mockscript", DateScriptMocksPlugin.LONG_PLUS_ONE_MONTH, params))
                         .dateHistogramInterval(DateHistogramInterval.MONTH)).execute().actionGet();
 
         assertSearchResponse(response);
@@ -799,8 +798,9 @@ public class DateHistogramIT extends ESIntegTestCase {
         Map<String, Object> params = new HashMap<>();
         params.put("fieldname", "date");
         SearchResponse response = client().prepareSearch("idx")
-                .addAggregation(dateHistogram("histo").script(new Script(ScriptType.INLINE, "native", DateScriptMocks.ExtractFieldScript.NAME,
-                    params)).dateHistogramInterval(DateHistogramInterval.MONTH))
+                .addAggregation(dateHistogram("histo").script(
+                    new Script(ScriptType.INLINE, "mockscript", DateScriptMocksPlugin.EXTRACT_FIELD, params))
+                    .dateHistogramInterval(DateHistogramInterval.MONTH))
                 .execute().actionGet();
 
         assertSearchResponse(response);
@@ -837,8 +837,9 @@ public class DateHistogramIT extends ESIntegTestCase {
         Map<String, Object> params = new HashMap<>();
         params.put("fieldname", "dates");
         SearchResponse response = client().prepareSearch("idx")
-                .addAggregation(dateHistogram("histo").script(new Script(ScriptType.INLINE, "native", DateScriptMocks.ExtractFieldScript.NAME,
-                    params)).dateHistogramInterval(DateHistogramInterval.MONTH))
+                .addAggregation(dateHistogram("histo").script(
+                    new Script(ScriptType.INLINE, "mockscript", DateScriptMocksPlugin.EXTRACT_FIELD, params))
+                    .dateHistogramInterval(DateHistogramInterval.MONTH))
                 .execute().actionGet();
 
         assertSearchResponse(response);
@@ -1329,7 +1330,7 @@ public class DateHistogramIT extends ESIntegTestCase {
         Map<String, Object> params = new HashMap<>();
         params.put("fieldname", "d");
         SearchResponse r = client().prepareSearch("cache_test_idx").setSize(0).addAggregation(dateHistogram("histo").field("d")
-                .script(new Script(ScriptType.INLINE, "native", DateScriptMocks.PlusOneMonthScript.NAME, params))
+                .script(new Script(ScriptType.INLINE, "mockscript", DateScriptMocksPlugin.LONG_PLUS_ONE_MONTH, params))
                 .dateHistogramInterval(DateHistogramInterval.MONTH)).get();
         assertSearchResponse(r);
 

+ 7 - 8
core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateRangeIT.java

@@ -26,7 +26,6 @@ import org.elasticsearch.plugins.Plugin;
 import org.elasticsearch.script.Script;
 import org.elasticsearch.script.ScriptType;
 import org.elasticsearch.search.aggregations.InternalAggregation;
-import org.elasticsearch.search.aggregations.bucket.DateScriptMocks.DateScriptsMockPlugin;
 import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
 import org.elasticsearch.search.aggregations.bucket.range.Range;
 import org.elasticsearch.search.aggregations.bucket.range.Range.Bucket;
@@ -40,6 +39,7 @@ import org.joda.time.DateTimeZone;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -111,8 +111,7 @@ public class DateRangeIT extends ESIntegTestCase {
 
     @Override
     protected Collection<Class<? extends Plugin>> nodePlugins() {
-        return Arrays.asList(
-                DateScriptsMockPlugin.class);
+        return Collections.singleton(DateScriptMocksPlugin.class);
     }
 
     public void testDateMath() throws Exception {
@@ -122,7 +121,7 @@ public class DateRangeIT extends ESIntegTestCase {
         if (randomBoolean()) {
             rangeBuilder.field("date");
         } else {
-            rangeBuilder.script(new Script(ScriptType.INLINE, "native", DateScriptMocks.ExtractFieldScript.NAME, params));
+            rangeBuilder.script(new Script(ScriptType.INLINE, "mockscript", DateScriptMocksPlugin.EXTRACT_FIELD, params));
         }
         SearchResponse response = client()
                 .prepareSearch("idx")
@@ -544,7 +543,7 @@ public class DateRangeIT extends ESIntegTestCase {
         SearchResponse response = client().prepareSearch("idx")
                 .addAggregation(dateRange("range")
                         .field("dates")
-                                .script(new Script(ScriptType.INLINE, "native", DateScriptMocks.PlusOneMonthScript.NAME, params))
+                                .script(new Script(ScriptType.INLINE, "mockscript", DateScriptMocksPlugin.DOUBLE_PLUS_ONE_MONTH, params))
                                 .addUnboundedTo(date(2, 15)).addRange(date(2, 15), date(3, 15)).addUnboundedFrom(date(3, 15))).execute()
                 .actionGet();
 
@@ -600,7 +599,7 @@ public class DateRangeIT extends ESIntegTestCase {
         params.put("fieldname", "date");
         SearchResponse response = client().prepareSearch("idx")
                 .addAggregation(dateRange("range")
-                        .script(new Script(ScriptType.INLINE, "native", DateScriptMocks.ExtractFieldScript.NAME, params))
+                        .script(new Script(ScriptType.INLINE, "mockscript", DateScriptMocksPlugin.EXTRACT_FIELD, params))
                         .addUnboundedTo(date(2, 15))
                         .addRange(date(2, 15), date(3, 15))
                         .addUnboundedFrom(date(3, 15)))
@@ -662,7 +661,7 @@ public class DateRangeIT extends ESIntegTestCase {
         SearchResponse response = client()
                 .prepareSearch("idx")
                 .addAggregation(
-                        dateRange("range").script(new Script(ScriptType.INLINE, "native", DateScriptMocks.ExtractFieldScript.NAME, params))
+                        dateRange("range").script(new Script(ScriptType.INLINE, "mockscript", DateScriptMocksPlugin.EXTRACT_FIELD, params))
                         .addUnboundedTo(date(2, 15)).addRange(date(2, 15), date(3, 15))
                         .addUnboundedFrom(date(3, 15))).execute().actionGet();
 
@@ -905,7 +904,7 @@ public class DateRangeIT extends ESIntegTestCase {
         Map<String, Object> params = new HashMap<>();
         params.put("fieldname", "date");
         SearchResponse r = client().prepareSearch("cache_test_idx").setSize(0).addAggregation(dateRange("foo").field("date")
-                .script(new Script(ScriptType.INLINE, "native", DateScriptMocks.PlusOneMonthScript.NAME, params))
+                .script(new Script(ScriptType.INLINE, "mockscript", DateScriptMocksPlugin.DOUBLE_PLUS_ONE_MONTH, params))
                 .addRange(new DateTime(2012, 1, 1, 0, 0, 0, 0, DateTimeZone.UTC), new DateTime(2013, 1, 1, 0, 0, 0, 0, DateTimeZone.UTC)))
                 .get();
         assertSearchResponse(r);

+ 0 - 130
core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateScriptMocks.java

@@ -1,130 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.search.aggregations.bucket;
-
-import org.elasticsearch.common.inject.internal.Nullable;
-import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.plugins.ScriptPlugin;
-import org.elasticsearch.script.AbstractSearchScript;
-import org.elasticsearch.script.ExecutableScript;
-import org.elasticsearch.script.NativeScriptFactory;
-import org.elasticsearch.script.ScriptModule;
-import org.joda.time.DateTime;
-import org.joda.time.DateTimeZone;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Mock scripts shared by DateRangeIT and DateHistogramIT
- */
-public class DateScriptMocks {
-
-    /**
-     * Mock plugin for the {@link DateScriptMocks.ExtractFieldScript} and {@link DateScriptMocks.PlusOneMonthScript}
-     */
-    public static class DateScriptsMockPlugin extends Plugin implements ScriptPlugin {
-        @Override
-        public List<NativeScriptFactory> getNativeScripts() {
-            return Arrays.asList(new ExtractFieldScriptFactory(), new PlusOneMonthScriptFactory());
-        }
-    }
-
-    public static class ExtractFieldScriptFactory implements NativeScriptFactory {
-        @Override
-        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
-            return new ExtractFieldScript((String) params.get("fieldname"));
-        }
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return ExtractFieldScript.NAME;
-        }
-    }
-
-    public static class ExtractFieldScript extends AbstractSearchScript {
-
-        public static final String NAME = "extract_field";
-        private String fieldname;
-
-        public ExtractFieldScript(String fieldname) {
-            this.fieldname  = fieldname;
-        }
-
-        @Override
-        public Object run() {
-            return doc().get(fieldname);
-        }
-    }
-
-    public static class PlusOneMonthScriptFactory implements NativeScriptFactory {
-
-        @Override
-        public ExecutableScript newScript(Map<String, Object> params) {
-            return new PlusOneMonthScript();
-        }
-
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return PlusOneMonthScript.NAME;
-        }
-    }
-
-    /**
-     * This mock script takes date field value and adds one month to the returned date
-     */
-    public static class PlusOneMonthScript extends AbstractSearchScript {
-
-        public static final String NAME = "date_plus_1_month";
-
-        private Map<String, Object> vars = new HashMap<>();
-
-        @Override
-        public void setNextVar(String name, Object value) {
-            vars.put(name, value);
-        }
-
-        @Override
-        public long runAsLong() {
-            return new DateTime((long) vars.get("_value"), DateTimeZone.UTC).plusMonths(1).getMillis();
-        }
-
-        @Override
-        public double runAsDouble() {
-            return new DateTime(Double.valueOf((double) vars.get("_value")).longValue(), DateTimeZone.UTC).plusMonths(1).getMillis();
-        }
-
-        @Override
-        public Object run() {
-            return new UnsupportedOperationException();
-        }
-    }
-}

+ 56 - 0
core/src/test/java/org/elasticsearch/search/aggregations/bucket/DateScriptMocksPlugin.java

@@ -0,0 +1,56 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.elasticsearch.search.aggregations.bucket;
+
+import org.elasticsearch.script.MockScriptPlugin;
+import org.elasticsearch.search.lookup.LeafDocLookup;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * Mock scripts shared by DateRangeIT and DateHistogramIT.
+ *
+ * Provides {@link DateScriptMocksPlugin#EXTRACT_FIELD}, {@link DateScriptMocksPlugin#DOUBLE_PLUS_ONE_MONTH},
+ * and {@link DateScriptMocksPlugin#LONG_PLUS_ONE_MONTH} scripts.
+ */
+public class DateScriptMocksPlugin extends MockScriptPlugin {
+    static final String EXTRACT_FIELD = "extract_field";
+    static final String DOUBLE_PLUS_ONE_MONTH = "double_date_plus_1_month";
+    static final String LONG_PLUS_ONE_MONTH = "long_date_plus_1_month";
+
+    @Override
+    public Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
+        Map<String, Function<Map<String, Object>, Object>> scripts = new HashMap<>();
+        scripts.put(EXTRACT_FIELD, params -> {
+            LeafDocLookup docLookup = (LeafDocLookup) params.get("doc");
+            String fieldname = (String) params.get("fieldname");
+            return docLookup.get(fieldname);
+        });
+        scripts.put(DOUBLE_PLUS_ONE_MONTH, params ->
+            new DateTime(Double.valueOf((double) params.get("_value")).longValue(), DateTimeZone.UTC).plusMonths(1).getMillis());
+        scripts.put(LONG_PLUS_ONE_MONTH, params ->
+            new DateTime((long) params.get("_value"), DateTimeZone.UTC).plusMonths(1).getMillis());
+        return scripts;
+    }
+}

+ 17 - 49
core/src/test/java/org/elasticsearch/search/aggregations/bucket/IpRangeIT.java

@@ -18,27 +18,23 @@
  */
 package org.elasticsearch.search.aggregations.bucket;
 
-import org.elasticsearch.action.search.SearchPhaseExecutionException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.function.Function;
+
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.search.SearchPhaseExecutionException;
 import org.elasticsearch.cluster.health.ClusterHealthStatus;
-import org.elasticsearch.common.inject.internal.Nullable;
 import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.plugins.ScriptPlugin;
-import org.elasticsearch.script.AbstractSearchScript;
-import org.elasticsearch.script.ExecutableScript;
-import org.elasticsearch.script.NativeScriptFactory;
+import org.elasticsearch.script.MockScriptPlugin;
 import org.elasticsearch.script.Script;
 import org.elasticsearch.script.ScriptType;
 import org.elasticsearch.search.aggregations.AggregationBuilders;
 import org.elasticsearch.search.aggregations.bucket.range.Range;
 import org.elasticsearch.test.ESIntegTestCase;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
 import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
 import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse;
 import static org.hamcrest.Matchers.containsString;
@@ -47,6 +43,13 @@ import static org.hamcrest.Matchers.instanceOf;
 @ESIntegTestCase.SuiteScopeTestCase
 public class IpRangeIT extends ESIntegTestCase {
 
+    public static class DummyScriptPlugin extends MockScriptPlugin {
+        @Override
+        public Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
+            return Collections.singletonMap("dummy", params -> null);
+        }
+    }
+
     @Override
     protected Collection<Class<? extends Plugin>> nodePlugins() {
         return Arrays.asList(DummyScriptPlugin.class);
@@ -210,7 +213,7 @@ public class IpRangeIT extends ESIntegTestCase {
         IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
                 () -> client().prepareSearch("idx").addAggregation(
                         AggregationBuilders.ipRange("my_range")
-                        .script(new Script(ScriptType.INLINE, "native", DummyScript.NAME, Collections.emptyMap())) ).get());
+                        .script(new Script(ScriptType.INLINE, "mockscript", "dummy", Collections.emptyMap())) ).get());
         assertThat(e.getMessage(), containsString("[ip_range] does not support scripts"));
     }
 
@@ -219,7 +222,7 @@ public class IpRangeIT extends ESIntegTestCase {
                 () -> client().prepareSearch("idx").addAggregation(
                         AggregationBuilders.ipRange("my_range")
                         .field("ip")
-                        .script(new Script(ScriptType.INLINE, "native", DummyScript.NAME, Collections.emptyMap())) ).get());
+                        .script(new Script(ScriptType.INLINE, "mockscript", "dummy", Collections.emptyMap())) ).get());
         assertThat(e.getMessage(), containsString("[ip_range] does not support scripts"));
     }
 
@@ -236,39 +239,4 @@ public class IpRangeIT extends ESIntegTestCase {
             assertEquals(rootCause.getMessage(), "No [ranges] specified for the [my_range] aggregation");
         }
     }
-
-    public static class DummyScriptPlugin extends Plugin implements ScriptPlugin {
-        @Override
-        public List<NativeScriptFactory> getNativeScripts() {
-            return Collections.singletonList(new DummyScriptFactory());
-        }
-    }
-
-    public static class DummyScriptFactory implements NativeScriptFactory {
-        public DummyScriptFactory() {}
-        @Override
-        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
-            return new DummyScript();
-        }
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return DummyScript.NAME;
-        }
-    }
-
-    private static class DummyScript extends AbstractSearchScript {
-
-        public static final String NAME = "dummy";
-
-        @Override
-        public Object run() {
-            return null;
-        }
-    }
-
 }

+ 21 - 10
core/src/test/java/org/elasticsearch/search/aggregations/bucket/SignificantTermsSignificanceScoreIT.java

@@ -31,16 +31,13 @@ import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.index.query.QueryParseContext;
 import org.elasticsearch.index.query.QueryShardException;
 import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.plugins.ScriptPlugin;
 import org.elasticsearch.plugins.SearchPlugin;
-import org.elasticsearch.script.NativeScriptFactory;
+import org.elasticsearch.script.MockScriptPlugin;
 import org.elasticsearch.script.Script;
 import org.elasticsearch.script.ScriptType;
 import org.elasticsearch.search.aggregations.Aggregation;
 import org.elasticsearch.search.aggregations.Aggregations;
 import org.elasticsearch.search.aggregations.bucket.filter.InternalFilter;
-import org.elasticsearch.search.aggregations.bucket.script.NativeSignificanceScoreScriptNoParams;
-import org.elasticsearch.search.aggregations.bucket.script.NativeSignificanceScoreScriptWithParams;
 import org.elasticsearch.search.aggregations.bucket.significant.SignificantTerms;
 import org.elasticsearch.search.aggregations.bucket.significant.SignificantTermsAggregatorFactory;
 import org.elasticsearch.search.aggregations.bucket.significant.heuristics.ChiSquare;
@@ -64,6 +61,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ExecutionException;
+import java.util.function.Function;
 
 import static java.util.Collections.singletonList;
 import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS;
@@ -168,7 +166,7 @@ public class SignificantTermsSignificanceScoreIT extends ESIntegTestCase {
         }
     }
 
-    public static class CustomSignificanceHeuristicPlugin extends Plugin implements ScriptPlugin, SearchPlugin {
+    public static class CustomSignificanceHeuristicPlugin extends MockScriptPlugin implements SearchPlugin {
         @Override
         public List<SearchExtensionSpec<SignificanceHeuristic, SignificanceHeuristicParser>> getSignificanceHeuristics() {
             return singletonList(new SearchExtensionSpec<SignificanceHeuristic, SignificanceHeuristicParser>(SimpleHeuristic.NAME,
@@ -176,9 +174,22 @@ public class SignificantTermsSignificanceScoreIT extends ESIntegTestCase {
         }
 
         @Override
-        public List<NativeScriptFactory> getNativeScripts() {
-            return Arrays.asList(new NativeSignificanceScoreScriptNoParams.Factory(),
-                    new NativeSignificanceScoreScriptWithParams.Factory());
+        public Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
+            Map<String, Function<Map<String, Object>, Object>> scripts = new HashMap<>();
+            scripts.put("script_with_params", params -> {
+                double factor = ((Number) params.get("param")).doubleValue();
+                return factor * (longValue(params.get("_subset_freq")) + longValue(params.get("_subset_size")) +
+                                 longValue(params.get("_superset_freq")) + longValue(params.get("_superset_size"))) / factor;
+            });
+            scripts.put("script_no_params", params ->
+                longValue(params.get("_subset_freq")) + longValue(params.get("_subset_size")) +
+                longValue(params.get("_superset_freq")) + longValue(params.get("_superset_size"))
+            );
+            return scripts;
+        }
+
+        private static long longValue(Object value) {
+            return ((ScriptHeuristic.LongAccessor) value).longValue();
         }
     }
 
@@ -514,9 +525,9 @@ public class SignificantTermsSignificanceScoreIT extends ESIntegTestCase {
         if (randomBoolean()) {
             Map<String, Object> params = new HashMap<>();
             params.put("param", randomIntBetween(1, 100));
-            script = new Script(ScriptType.INLINE, "native", "native_significance_score_script_with_params", params);
+            script = new Script(ScriptType.INLINE, "mockscript", "script_with_params", params);
         } else {
-            script = new Script(ScriptType.INLINE, "native", "native_significance_score_script_no_params", Collections.emptyMap());
+            script = new Script(ScriptType.INLINE, "mockscript", "script_no_params", Collections.emptyMap());
         }
         return new ScriptHeuristic(script);
     }

+ 78 - 35
core/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptIT.java

@@ -19,22 +19,29 @@
 
 package org.elasticsearch.search.functionscore;
 
+import org.apache.lucene.index.LeafReaderContext;
 import org.apache.lucene.search.Explanation;
 import org.elasticsearch.action.index.IndexRequestBuilder;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.search.SearchType;
 import org.elasticsearch.common.Nullable;
 import org.elasticsearch.common.lucene.search.function.CombineFunction;
+import org.elasticsearch.common.settings.Settings;
 import org.elasticsearch.index.fielddata.ScriptDocValues;
 import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.script.AbstractDoubleSearchScript;
+import org.elasticsearch.plugins.ScriptPlugin;
+import org.elasticsearch.script.CompiledScript;
 import org.elasticsearch.script.ExecutableScript;
 import org.elasticsearch.script.ExplainableSearchScript;
-import org.elasticsearch.script.NativeScriptFactory;
+import org.elasticsearch.script.LeafSearchScript;
 import org.elasticsearch.script.Script;
+import org.elasticsearch.script.ScriptEngine;
 import org.elasticsearch.script.ScriptType;
+import org.elasticsearch.script.SearchScript;
 import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.SearchHits;
+import org.elasticsearch.search.lookup.LeafDocLookup;
+import org.elasticsearch.search.lookup.SearchLookup;
 import org.elasticsearch.test.ESIntegTestCase;
 import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
 import org.elasticsearch.test.ESIntegTestCase.Scope;
@@ -60,12 +67,77 @@ import static org.hamcrest.Matchers.equalTo;
 
 @ClusterScope(scope = Scope.SUITE, supportsDedicatedMasters = false, numDataNodes = 1)
 public class ExplainableScriptIT extends ESIntegTestCase {
+
+    public static class ExplainableScriptPlugin extends Plugin implements ScriptPlugin {
+        @Override
+        public ScriptEngine getScriptEngine(Settings settings) {
+            return new ScriptEngine() {
+                @Override
+                public String getType() {
+                    return "test";
+                }
+
+                @Override
+                public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
+                    assert scriptSource.equals("explainable_script");
+                    return null;
+                }
+
+                @Override
+                public ExecutableScript executable(CompiledScript compiledScript, @Nullable Map<String, Object> vars) {
+                    throw new UnsupportedOperationException();
+                }
+
+                @Override
+                public SearchScript search(CompiledScript compiledScript, SearchLookup lookup, @Nullable Map<String, Object> vars) {
+                    return new SearchScript() {
+                        @Override
+                        public LeafSearchScript getLeafSearchScript(LeafReaderContext context) throws IOException {
+                            return new MyScript(lookup.doc().getLeafDocLookup(context));
+                        }
+                        @Override
+                        public boolean needsScores() {
+                            return false;
+                        }
+                    };
+                }
+
+                @Override
+                public void close() {}
+            };
+        }
+    }
+
+    static class MyScript implements ExplainableSearchScript {
+        LeafDocLookup docLookup;
+
+        MyScript(LeafDocLookup docLookup) {
+            this.docLookup = docLookup;
+        }
+
+        @Override
+        public void setDocument(int doc) {
+            docLookup.setDocument(doc);
+        }
+
+        @Override
+        public Explanation explain(Explanation subQueryScore) throws IOException {
+            Explanation scoreExp = Explanation.match(subQueryScore.getValue(), "_score: ", subQueryScore);
+            return Explanation.match((float) (runAsDouble()), "This script returned " + runAsDouble(), scoreExp);
+        }
+
+        @Override
+        public double runAsDouble() {
+            return ((Number) ((ScriptDocValues) docLookup.get("number_field")).getValues().get(0)).doubleValue();
+        }
+    }
+
     @Override
     protected Collection<Class<? extends Plugin>> nodePlugins() {
         return Arrays.asList(ExplainableScriptPlugin.class);
     }
 
-    public void testNativeExplainScript() throws InterruptedException, IOException, ExecutionException {
+    public void testExplainScript() throws InterruptedException, IOException, ExecutionException {
         List<IndexRequestBuilder> indexRequests = new ArrayList<>();
         for (int i = 0; i < 20; i++) {
             indexRequests.add(client().prepareIndex("test", "type").setId(Integer.toString(i)).setSource(
@@ -78,7 +150,7 @@ public class ExplainableScriptIT extends ESIntegTestCase {
                         searchSource().explain(true).query(
                                 functionScoreQuery(termQuery("text", "text"),
                                         scriptFunction(
-                                            new Script(ScriptType.INLINE, "native", "native_explainable_script", Collections.emptyMap())))
+                                            new Script(ScriptType.INLINE, "test", "explainable_script", Collections.emptyMap())))
                                         .boostMode(CombineFunction.REPLACE)))).actionGet();
 
         ElasticsearchAssertions.assertNoFailures(response);
@@ -89,39 +161,10 @@ public class ExplainableScriptIT extends ESIntegTestCase {
             assertThat(hit.getId(), equalTo(Integer.toString(idCounter)));
             assertThat(hit.getExplanation().toString(),
                     containsString(Double.toString(idCounter) + " = This script returned " + Double.toString(idCounter)));
-            assertThat(hit.getExplanation().toString(), containsString("freq=1.0 = termFreq=1.0"));
+            assertThat(hit.getExplanation().toString(), containsString("freq=1.0"));
+            assertThat(hit.getExplanation().toString(), containsString("termFreq=1.0"));
             assertThat(hit.getExplanation().getDetails().length, equalTo(2));
             idCounter--;
         }
     }
-
-    public static class MyNativeScriptFactory implements NativeScriptFactory {
-        @Override
-        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
-            return new MyScript();
-        }
-        @Override
-        public boolean needsScores() {
-            return true;
-        }
-
-        @Override
-        public String getName() {
-            return "native_explainable_script";
-        }
-    }
-
-    static class MyScript extends AbstractDoubleSearchScript implements ExplainableSearchScript, ExecutableScript {
-
-        @Override
-        public Explanation explain(Explanation subQueryScore) throws IOException {
-            Explanation scoreExp = Explanation.match(subQueryScore.getValue(), "_score: ", subQueryScore);
-            return Explanation.match((float) (runAsDouble()), "This script returned " + runAsDouble(), scoreExp);
-        }
-
-        @Override
-        public double runAsDouble() {
-            return ((Number) ((ScriptDocValues) doc().get("number_field")).getValues().get(0)).doubleValue();
-        }
-    }
 }

+ 0 - 35
core/src/test/java/org/elasticsearch/search/functionscore/ExplainableScriptPlugin.java

@@ -1,35 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.search.functionscore;
-
-import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.plugins.ScriptPlugin;
-import org.elasticsearch.script.NativeScriptFactory;
-
-
-import java.util.Collections;
-import java.util.List;
-
-public class ExplainableScriptPlugin extends Plugin implements ScriptPlugin {
-    @Override
-    public List<NativeScriptFactory> getNativeScripts() {
-        return Collections.singletonList(new ExplainableScriptIT.MyNativeScriptFactory());
-    }
-}

+ 0 - 117
core/src/test/java/org/elasticsearch/update/UpdateByNativeScriptIT.java

@@ -1,117 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.elasticsearch.update;
-
-import org.elasticsearch.common.Nullable;
-import org.elasticsearch.plugins.Plugin;
-import org.elasticsearch.plugins.ScriptPlugin;
-import org.elasticsearch.script.AbstractExecutableScript;
-import org.elasticsearch.script.ExecutableScript;
-import org.elasticsearch.script.NativeScriptEngine;
-import org.elasticsearch.script.NativeScriptFactory;
-import org.elasticsearch.script.Script;
-import org.elasticsearch.script.ScriptType;
-import org.elasticsearch.test.ESIntegTestCase;
-import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
-import org.elasticsearch.test.ESIntegTestCase.Scope;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.hamcrest.Matchers.hasKey;
-import static org.hamcrest.Matchers.is;
-
-@ClusterScope(scope= Scope.SUITE, numDataNodes =1)
-public class UpdateByNativeScriptIT extends ESIntegTestCase {
-
-    @Override
-    protected Collection<Class<? extends Plugin>> nodePlugins() {
-        return Arrays.asList(CustomNativeScriptFactory.TestPlugin.class);
-    }
-
-    public void testThatUpdateUsingNativeScriptWorks() throws Exception {
-        createIndex("test");
-
-        index("test", "type", "1", "text", "value");
-
-        Map<String, Object> params = new HashMap<>();
-        params.put("foo", "SETVALUE");
-        client().prepareUpdate("test", "type", "1")
-                .setScript(new Script(ScriptType.INLINE, NativeScriptEngine.NAME, "custom", params)).get();
-
-        Map<String, Object> data = client().prepareGet("test", "type", "1").get().getSource();
-        assertThat(data, hasKey("foo"));
-        assertThat(data.get("foo").toString(), is("SETVALUE"));
-    }
-
-    public static class CustomNativeScriptFactory implements NativeScriptFactory  {
-        public static class TestPlugin extends Plugin implements ScriptPlugin {
-            @Override
-            public List<NativeScriptFactory> getNativeScripts() {
-                return Collections.singletonList(new CustomNativeScriptFactory());
-            }
-        }
-        @Override
-        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
-            return new CustomScript(params);
-        }
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return "custom";
-        }
-    }
-
-    static class CustomScript extends AbstractExecutableScript {
-        private Map<String, Object> params;
-        private Map<String, Object> vars = new HashMap<>(2);
-
-        CustomScript(Map<String, Object> params) {
-            this.params = params;
-        }
-
-        @Override
-        public Object run() {
-            if (vars.containsKey("ctx") && vars.get("ctx") instanceof Map) {
-                Map ctx = (Map) vars.get("ctx");
-                if (ctx.containsKey("_source") && ctx.get("_source") instanceof Map) {
-                    Map source = (Map) ctx.get("_source");
-                    source.putAll(params);
-                }
-            }
-            // return value does not matter, the UpdateHelper class
-            return null;
-        }
-
-        @Override
-        public void setNextVar(String name, Object value) {
-            vars.put(name, value);
-        }
-
-    }
-
-}

+ 5 - 0
docs/reference/migration/migrate_6_0/scripting.asciidoc

@@ -6,6 +6,11 @@
 The Groovy, JavaScript, and Python scripting languages were deprecated in
 elasticsearch 5.0 and have now been removed. Use painless instead.
 
+==== Native scripts removed
+
+Native scripts have been removed. Instead,
+<<modules-scripting-engine, implement a `ScriptEngine`>>.
+
 ==== Date fields now return dates
 
 `doc.some_date_field.value` now returns ++ReadableDateTime++s instead of

+ 22 - 5
test/framework/src/main/java/org/elasticsearch/script/MockScriptEngine.java

@@ -183,13 +183,22 @@ public class MockScriptEngine implements ScriptEngine {
                 ctx.putAll(vars);
             }
 
-            AbstractSearchScript leafSearchScript = new AbstractSearchScript() {
-
+            return new LeafSearchScript() {
                 @Override
                 public Object run() {
                     return script.apply(ctx);
                 }
 
+                @Override
+                public long runAsLong() {
+                    return ((Number) run()).longValue();
+                }
+
+                @Override
+                public double runAsDouble() {
+                    return ((Number) run()).doubleValue();
+                }
+
                 @Override
                 public void setNextVar(String name, Object value) {
                     ctx.put(name, value);
@@ -197,12 +206,20 @@ public class MockScriptEngine implements ScriptEngine {
 
                 @Override
                 public void setScorer(Scorer scorer) {
-                    super.setScorer(scorer);
                     ctx.put("_score", new ScoreAccessor(scorer));
                 }
+
+                @Override
+                public void setDocument(int doc) {
+                    leafLookup.setDocument(doc);
+                }
+
+                @Override
+                public void setSource(Map<String, Object> source) {
+                    leafLookup.source().setSource(source);
+                }
+
             };
-            leafSearchScript.setLookup(leafLookup);
-            return leafSearchScript;
         }
 
         @Override

+ 0 - 58
test/framework/src/main/java/org/elasticsearch/search/aggregations/bucket/script/NativeSignificanceScoreScriptNoParams.java

@@ -1,58 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.search.aggregations.bucket.script;
-
-import org.elasticsearch.common.Nullable;
-import org.elasticsearch.script.ExecutableScript;
-import org.elasticsearch.script.NativeScriptFactory;
-
-import java.util.Map;
-
-public class NativeSignificanceScoreScriptNoParams extends TestScript {
-
-    public static final String NATIVE_SIGNIFICANCE_SCORE_SCRIPT_NO_PARAMS = "native_significance_score_script_no_params";
-
-    public static class Factory implements NativeScriptFactory {
-
-        @Override
-        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
-            return new NativeSignificanceScoreScriptNoParams();
-        }
-
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return NATIVE_SIGNIFICANCE_SCORE_SCRIPT_NO_PARAMS;
-        }
-    }
-
-    private NativeSignificanceScoreScriptNoParams() {
-    }
-
-    @Override
-    public Object run() {
-        checkParams();
-        return _subset_freq.longValue() + _subset_size.longValue() + _superset_freq.longValue() + _superset_size.longValue();
-    }
-}

+ 0 - 63
test/framework/src/main/java/org/elasticsearch/search/aggregations/bucket/script/NativeSignificanceScoreScriptWithParams.java

@@ -1,63 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.search.aggregations.bucket.script;
-
-import org.elasticsearch.common.Nullable;
-import org.elasticsearch.script.ExecutableScript;
-import org.elasticsearch.script.NativeScriptFactory;
-
-import java.util.Map;
-import java.util.Objects;
-
-public class NativeSignificanceScoreScriptWithParams extends TestScript {
-
-    public static final String NATIVE_SIGNIFICANCE_SCORE_SCRIPT_WITH_PARAMS = "native_significance_score_script_with_params";
-    double factor = 0.0;
-
-    public static class Factory implements NativeScriptFactory {
-
-        @Override
-        public ExecutableScript newScript(@Nullable Map<String, Object> params) {
-            return new NativeSignificanceScoreScriptWithParams(params);
-        }
-
-        @Override
-        public boolean needsScores() {
-            return false;
-        }
-
-        @Override
-        public String getName() {
-            return NATIVE_SIGNIFICANCE_SCORE_SCRIPT_WITH_PARAMS;
-        }
-    }
-
-    private NativeSignificanceScoreScriptWithParams(Map<String, Object> params) {
-        factor = ((Number) params.get("param")).doubleValue();
-    }
-
-    @Override
-    public Object run() {
-        checkParams();
-        Objects.requireNonNull(factor, "factor");
-        return factor * (_subset_freq.longValue() + _subset_size.longValue() + _superset_freq.longValue() + _superset_size.longValue()) / factor;
-    }
-
-}

+ 0 - 59
test/framework/src/main/java/org/elasticsearch/search/aggregations/bucket/script/TestScript.java

@@ -1,59 +0,0 @@
-/*
- * Licensed to Elasticsearch under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.elasticsearch.search.aggregations.bucket.script;
-
-import java.util.Objects;
-
-import org.elasticsearch.script.ExecutableScript;
-import org.elasticsearch.search.aggregations.bucket.significant.heuristics.ScriptHeuristic;
-
-public abstract class TestScript implements ExecutableScript{
-
-    ScriptHeuristic.LongAccessor _subset_freq;
-    ScriptHeuristic.LongAccessor _subset_size;
-    ScriptHeuristic.LongAccessor _superset_freq;
-    ScriptHeuristic.LongAccessor _superset_size;
-
-    protected TestScript() {
-    }
-
-    @Override
-    public void setNextVar(String name, Object value) {
-        if (name.equals("_subset_freq")) {
-            _subset_freq = (ScriptHeuristic.LongAccessor)value;
-        }
-        if (name.equals("_subset_size")) {
-            _subset_size = (ScriptHeuristic.LongAccessor)value;
-        }
-        if (name.equals("_superset_freq")) {
-            _superset_freq = (ScriptHeuristic.LongAccessor)value;
-        }
-        if (name.equals("_superset_size")) {
-            _superset_size = (ScriptHeuristic.LongAccessor)value;
-        }
-    }
-
-    protected final void checkParams() {
-        Objects.requireNonNull(_subset_freq, "_subset_freq");
-        Objects.requireNonNull(_subset_size, "_subset_size");
-        Objects.requireNonNull(_superset_freq, "_superset_freq");
-        Objects.requireNonNull(_superset_size, "_superset_size");
-    }
-}