Repository: incubator-tinkerpop Updated Branches: refs/heads/TINKERPOP3-860 [created] b503e4155 Adjusted ScriptEngines to "merge" bindings. Bindings from plugins were being pushed into the ScriptEngine context but were not being merged into the bindings used on eval. They had to be merged together. In doing this, I also found a bug where plugins could conflict with one another (i.e. the first plugin would install, then the second would come along an blow out what the previous one had done) - fixed that. Added test cases to cover these scenarios. Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/b503e415 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/b503e415 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/b503e415 Branch: refs/heads/TINKERPOP3-860 Commit: b503e41552e533bc4420a968ba591faacd1c6e27 Parents: 59eaa06 Author: Stephen Mallette Authored: Wed Dec 2 12:44:36 2015 -0500 Committer: Stephen Mallette Committed: Wed Dec 2 12:44:36 2015 -0500 ---------------------------------------------------------------------- .../GremlinGroovyScriptEngineOverGraphTest.java | 7 +- .../gremlin/groovy/engine/ScriptEngines.java | 24 ++++- .../jsr223/GremlinGroovyScriptEngine.java | 19 +++- .../jsr223/ScriptEnginePluginAcceptor.java | 26 +++-- .../groovy/engine/ScriptEnginesTest.java | 99 ++++++++++++++++++++ .../jsr223/GremlinGroovyScriptEngineTest.java | 35 ++++++- .../structure/io/script/ScriptRecordReader.java | 3 +- .../structure/io/script/ScriptRecordWriter.java | 3 +- 8 files changed, 194 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b503e415/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineOverGraphTest.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineOverGraphTest.java b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineOverGraphTest.java index 5e93d1c..17e1cf0 100644 --- a/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineOverGraphTest.java +++ b/gremlin-groovy-test/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineOverGraphTest.java @@ -23,6 +23,7 @@ import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.tinkerpop.gremlin.AbstractGremlinTest; import org.apache.tinkerpop.gremlin.FeatureRequirementSet; import org.apache.tinkerpop.gremlin.LoadGraphWith; +import org.apache.tinkerpop.gremlin.groovy.CompilerCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.DefaultImportCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.NoImportCustomizerProvider; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; @@ -72,7 +73,7 @@ public class GremlinGroovyScriptEngineOverGraphTest extends AbstractGremlinTest @Test @LoadGraphWith(LoadGraphWith.GraphData.MODERN) public void shouldLoadImports() throws Exception { - final ScriptEngine engineNoImports = new GremlinGroovyScriptEngine(NoImportCustomizerProvider.INSTANCE); + final ScriptEngine engineNoImports = new GremlinGroovyScriptEngine((CompilerCustomizerProvider) NoImportCustomizerProvider.INSTANCE); try { engineNoImports.eval("Vertex.class.getName()"); fail("Should have thrown an exception because no imports were supplied"); @@ -80,7 +81,7 @@ public class GremlinGroovyScriptEngineOverGraphTest extends AbstractGremlinTest assertTrue(se instanceof ScriptException); } - final ScriptEngine engineWithImports = new GremlinGroovyScriptEngine(new DefaultImportCustomizerProvider()); + final ScriptEngine engineWithImports = new GremlinGroovyScriptEngine((CompilerCustomizerProvider) new DefaultImportCustomizerProvider()); engineWithImports.put("g", g); assertEquals(Vertex.class.getName(), engineWithImports.eval("Vertex.class.getName()")); assertEquals(2l, engineWithImports.eval("g.V().has('age',gt(30)).count().next()")); @@ -93,7 +94,7 @@ public class GremlinGroovyScriptEngineOverGraphTest extends AbstractGremlinTest @Test @LoadGraphWith(LoadGraphWith.GraphData.MODERN) public void shouldLoadStandardImportsAndThenAddToThem() throws Exception { - final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(new DefaultImportCustomizerProvider()); + final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine((CompilerCustomizerProvider) new DefaultImportCustomizerProvider()); engine.put("g", g); assertEquals(Vertex.class.getName(), engine.eval("Vertex.class.getName()")); assertEquals(2l, engine.eval("g.V().has('age',gt(30)).count().next()")); http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b503e415/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java index 70a47a6..a03acee 100644 --- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java +++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEngines.java @@ -31,6 +31,7 @@ import org.slf4j.LoggerFactory; import javax.script.Bindings; import javax.script.Compilable; import javax.script.CompiledScript; +import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; @@ -93,7 +94,11 @@ public class ScriptEngines implements AutoCloseable { throw new IllegalArgumentException(String.format("Language [%s] not supported", language)); awaitControlOp(); - return scriptEngines.get(language).eval(script, bindings); + + final ScriptEngine engine = scriptEngines.get(language); + final Bindings all = mergeBindings(bindings, engine); + + return engine.eval(script, all); } /** @@ -105,7 +110,11 @@ public class ScriptEngines implements AutoCloseable { throw new IllegalArgumentException("Language [%s] not supported"); awaitControlOp(); - return scriptEngines.get(language).eval(reader, bindings); + + final ScriptEngine engine = scriptEngines.get(language); + final Bindings all = mergeBindings(bindings, engine); + + return engine.eval(reader, all); } /** @@ -389,4 +398,15 @@ public class ScriptEngines implements AutoCloseable { } } + /** + * Takes the bindings from a request for eval and merges them with the {@code ENGINE_SCOPE} bindings. + */ + private static Bindings mergeBindings(final Bindings bindings, final ScriptEngine engine) { + // plugins place "globals" here - see ScriptEnginePluginAcceptor + final Bindings all = engine.getBindings(ScriptContext.ENGINE_SCOPE); + + // merge the globals with the incoming bindings where local bindings "win" + all.putAll(bindings); + return all; + } } http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b503e415/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java index 2feaf71..72e38c3 100644 --- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java +++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngine.java @@ -286,7 +286,7 @@ public class GremlinGroovyScriptEngine extends GroovyScriptEngineImpl implements // use the EmptyImportCustomizer because it doesn't come with static initializers containing // existing imports. importCustomizerProvider = new EmptyImportCustomizerProvider(importCustomizerProvider, imports, staticImports); - reset(); + internalReset(); } /** @@ -315,6 +315,19 @@ public class GremlinGroovyScriptEngine extends GroovyScriptEngineImpl implements */ @Override public void reset() { + internalReset(); + + loadedPlugins.clear(); + + getContext().getBindings(ScriptContext.ENGINE_SCOPE).clear(); + } + + /** + * Resets the {@code ScriptEngine} but does not clear the loaded plugins or bindings. Typically called by + * {@link DependencyManager} methods that need to just force the classloader to be recreated and script caches + * cleared. + */ + private void internalReset() { createClassLoader(); // must clear the local cache here because the the classloader has been reset. therefore, classes previously @@ -322,12 +335,8 @@ public class GremlinGroovyScriptEngine extends GroovyScriptEngineImpl implements classMap.clear(); globalClosures.clear(); - loadedPlugins.clear(); - final Set toReuse = new HashSet<>(artifactsToUse); toReuse.forEach(this::use); - - getContext().getBindings(ScriptContext.ENGINE_SCOPE).clear(); } /** http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b503e415/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ScriptEnginePluginAcceptor.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ScriptEnginePluginAcceptor.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ScriptEnginePluginAcceptor.java index 00817b1..1a72864 100644 --- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ScriptEnginePluginAcceptor.java +++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/ScriptEnginePluginAcceptor.java @@ -29,6 +29,9 @@ import java.util.Map; import java.util.Set; /** + * A {@link PluginAcceptor} implementation for bare {@code ScriptEngine} implementations allowing plugins to + * interact with them on initialization. + * * @author Stephen Mallette (http://stephen.genoprime.com) */ public class ScriptEnginePluginAcceptor implements PluginAcceptor { @@ -38,19 +41,27 @@ public class ScriptEnginePluginAcceptor implements PluginAcceptor { this.scriptEngine = scriptEngine; } + /** + * Adds global bindings to the {@code ScriptEngine} that will be applied to every evaluated script. + */ @Override public void addBinding(final String key, final Object val) { - scriptEngine.getContext().setAttribute(key, val, ScriptContext.GLOBAL_SCOPE); + // added to the engine scope because the plugin will be applied to each scriptengine independently anyway + scriptEngine.getContext().setAttribute(key, val, ScriptContext.ENGINE_SCOPE); } + /** + * Gets the global bindings that will be applied to every evaluated script. + */ @Override public Map getBindings() { - return scriptEngine.getBindings(ScriptContext.GLOBAL_SCOPE); + // as these "global" bindings were added to engine scope they should be pulled from the same place + return scriptEngine.getBindings(ScriptContext.ENGINE_SCOPE); } /** - * If the ScriptEngine implements the DependencyManager interface it will try to import the specified - * import statements. + * If the {@code ScriptEngine} implements the {@link DependencyManager} interface it will try to import the + * specified import statements. */ @Override public void addImports(final Set importStatements) { @@ -59,14 +70,17 @@ public class ScriptEnginePluginAcceptor implements PluginAcceptor { } /** - * Evaluate a script in the ScriptEngine. Typically eval() should be called after imports as ScriptEngine - * resets may occur during import. + * Evaluate a script in the {@code ScriptEngine}. Typically {@code eval()} should be called after imports as + * {@code ScriptEngine} resets may occur during import. */ @Override public Object eval(final String script) throws ScriptException { return this.scriptEngine.eval(script); } + /** + * Defines the environment settings for the {@link GremlinPlugin}. + */ @Override public Map environment() { final Map env = new HashMap<>(); http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b503e415/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEnginesTest.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEnginesTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEnginesTest.java index 39e14fd..940a530 100644 --- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEnginesTest.java +++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/engine/ScriptEnginesTest.java @@ -18,15 +18,23 @@ */ package org.apache.tinkerpop.gremlin.groovy.engine; +import org.apache.tinkerpop.gremlin.groovy.plugin.GremlinPlugin; +import org.apache.tinkerpop.gremlin.groovy.plugin.IllegalEnvironmentException; +import org.apache.tinkerpop.gremlin.groovy.plugin.PluginAcceptor; +import org.apache.tinkerpop.gremlin.groovy.plugin.PluginInitializationException; import org.junit.Test; +import javax.script.Bindings; import javax.script.SimpleBindings; +import java.awt.*; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.IntStream; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** @@ -34,6 +42,97 @@ import static org.junit.Assert.assertTrue; */ public class ScriptEnginesTest { @Test + public void shouldMergeBindingsFromLocalAndGlobal() throws Exception { + final ScriptEngines engines = new ScriptEngines(se -> {}); + engines.reload("gremlin-groovy", Collections.emptySet(), + Collections.emptySet(), Collections.emptyMap()); + + engines.loadPlugins(Arrays.asList(new GremlinPlugin() { + @Override + public String getName() { + return "mock"; + } + + @Override + public void pluginTo(final PluginAcceptor pluginAcceptor) throws IllegalEnvironmentException, PluginInitializationException { + pluginAcceptor.addBinding("y", "here"); + } + })); + + final Bindings localBindings = new SimpleBindings(); + localBindings.put("x", "there"); + + assertEquals("herethere", engines.eval("y+x", localBindings, "gremlin-groovy")); + } + + @Test + public void shouldMergeBindingsFromLocalAndGlobalWithMultiplePlugins() throws Exception { + final ScriptEngines engines = new ScriptEngines(se -> {}); + engines.reload("gremlin-groovy", Collections.emptySet(), + Collections.emptySet(), Collections.emptyMap()); + + engines.loadPlugins(Arrays.asList(new GremlinPlugin() { + @Override + public String getName() { + return "mock1"; + } + + @Override + public void pluginTo(final PluginAcceptor pluginAcceptor) throws IllegalEnvironmentException, PluginInitializationException { + pluginAcceptor.addBinding("y", "here"); + } + })); + + final Bindings localBindings = new SimpleBindings(); + localBindings.put("x", "there"); + + assertEquals("herethere", engines.eval("y+x", localBindings, "gremlin-groovy")); + + engines.loadPlugins(Arrays.asList(new GremlinPlugin() { + @Override + public String getName() { + return "mock2"; + } + + @Override + public void pluginTo(final PluginAcceptor pluginAcceptor) throws IllegalEnvironmentException, PluginInitializationException { + pluginAcceptor.addBinding("z", "where"); + pluginAcceptor.addImports(new HashSet<>(Arrays.asList("import java.awt.Color"))); + } + })); + + assertEquals("heretherewhere", engines.eval("y+x+z", localBindings, "gremlin-groovy")); + assertEquals(Color.RED, engines.eval("Color.RED", localBindings, "gremlin-groovy")); + + } + + @Test + public void shouldMergeBindingsWhereLocalOverridesGlobal() throws Exception { + final ScriptEngines engines = new ScriptEngines(se -> {}); + engines.reload("gremlin-groovy", Collections.emptySet(), + Collections.emptySet(), Collections.emptyMap()); + + engines.loadPlugins(Arrays.asList(new GremlinPlugin() { + @Override + public String getName() { + return "mock"; + } + + @Override + public void pluginTo(final PluginAcceptor pluginAcceptor) throws IllegalEnvironmentException, PluginInitializationException { + pluginAcceptor.addBinding("y", "here"); + } + })); + + // the "y" below should override the global variable setting. + final Bindings localBindings = new SimpleBindings(); + localBindings.put("y", "there"); + localBindings.put("z", "where"); + + assertEquals("therewhere", engines.eval("y+z", localBindings, "gremlin-groovy")); + } + + @Test public void shouldFailUntilImportExecutes() throws Exception { final ScriptEngines engines = new ScriptEngines(se -> {}); engines.reload("gremlin-groovy", Collections.emptySet(), http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b503e415/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java ---------------------------------------------------------------------- diff --git a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java index 9e74686..7480e01 100644 --- a/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java +++ b/gremlin-groovy/src/test/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineTest.java @@ -19,6 +19,7 @@ package org.apache.tinkerpop.gremlin.groovy.jsr223; import groovy.lang.Closure; +import org.apache.tinkerpop.gremlin.groovy.CompilerCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.NoImportCustomizerProvider; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils; @@ -29,6 +30,7 @@ import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptException; import javax.script.SimpleBindings; +import java.awt.*; import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -98,7 +100,7 @@ public class GremlinGroovyScriptEngineTest { @Test public void shouldLoadImportsViaDependencyManagerInterface() throws Exception { - final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(NoImportCustomizerProvider.INSTANCE); + final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine((CompilerCustomizerProvider) NoImportCustomizerProvider.INSTANCE); try { engine.eval("Vertex.class.getName()"); fail("Should have thrown an exception because no imports were supplied"); @@ -112,7 +114,7 @@ public class GremlinGroovyScriptEngineTest { @Test public void shouldLoadImportsViaDependencyManagerInterfaceAdditively() throws Exception { - final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(NoImportCustomizerProvider.INSTANCE); + final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine((CompilerCustomizerProvider) NoImportCustomizerProvider.INSTANCE); try { engine.eval("Vertex.class.getName()"); fail("Should have thrown an exception because no imports were supplied"); @@ -144,7 +146,7 @@ public class GremlinGroovyScriptEngineTest { @Test public void shouldLoadImportsViaDependencyManagerFromDependencyGatheredByUse() throws Exception { - final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(NoImportCustomizerProvider.INSTANCE); + final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine((CompilerCustomizerProvider) NoImportCustomizerProvider.INSTANCE); try { engine.eval("org.apache.commons.math3.util.FastMath.abs(-1235)"); fail("Should have thrown an exception because no imports were supplied"); @@ -159,7 +161,7 @@ public class GremlinGroovyScriptEngineTest { @Test public void shouldAllowsUseToBeExecutedAfterImport() throws Exception { - final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(NoImportCustomizerProvider.INSTANCE); + final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine((CompilerCustomizerProvider) NoImportCustomizerProvider.INSTANCE); try { engine.eval("org.apache.commons.math3.util.FastMath.abs(-1235)"); fail("Should have thrown an exception because no imports were supplied"); @@ -173,6 +175,31 @@ public class GremlinGroovyScriptEngineTest { } @Test + public void shouldAllowsMultipleImports() throws Exception { + final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine((CompilerCustomizerProvider) NoImportCustomizerProvider.INSTANCE); + try { + engine.eval("Color.RED"); + fail("Should have thrown an exception because no imports were supplied"); + } catch (Exception se) { + assertTrue(se instanceof ScriptException); + } + + try { + engine.eval("SystemColor.ACTIVE_CAPTION"); + fail("Should have thrown an exception because no imports were supplied"); + } catch (Exception se) { + assertTrue(se instanceof ScriptException); + } + + engine.addImports(new HashSet<>(Arrays.asList("import java.awt.Color"))); + assertEquals(Color.RED, engine.eval("Color.RED")); + + engine.addImports(new HashSet<>(Arrays.asList("import java.awt.SystemColor"))); + assertEquals(Color.RED, engine.eval("Color.RED")); + assertEquals(SystemColor.ACTIVE_CAPTION, engine.eval("SystemColor.ACTIVE_CAPTION")); + } + + @Test public void shouldClearEngineScopeOnReset() throws Exception { final GremlinGroovyScriptEngine engine = new GremlinGroovyScriptEngine(); engine.eval("x = { y -> y + 1}"); http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/b503e415/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/script/ScriptRecordReader.java ---------------------------------------------------------------------- diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/script/ScriptRecordReader.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/script/ScriptRecordReader.java index e56eb1a..4cc1602 100644 --- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/script/ScriptRecordReader.java +++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/structure/io/script/ScriptRecordReader.java @@ -26,6 +26,7 @@ import org.apache.hadoop.mapreduce.InputSplit; import org.apache.hadoop.mapreduce.RecordReader; import org.apache.hadoop.mapreduce.TaskAttemptContext; import org.apache.hadoop.mapreduce.lib.input.LineRecordReader; +import org.apache.tinkerpop.gremlin.groovy.CompilerCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.DefaultImportCustomizerProvider; import org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngine; import org.apache.tinkerpop.gremlin.hadoop.structure.io.VertexWritable; @@ -64,7 +65,7 @@ public final class ScriptRecordReader extends RecordReader