You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2017/02/15 00:34:54 UTC
[4/6] tinkerpop git commit: TINKERPOP-1631 Improved consistency of
binding application to GremlinScriptEngine
TINKERPOP-1631 Improved consistency of binding application to GremlinScriptEngine
Added a base factory class. Added start of a test framework for GremlinScriptEngineFactory. Pushed all bindings to global - engine is overriden at time of eval() by "parameters".
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/48185654
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/48185654
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/48185654
Branch: refs/heads/TINKERPOP-1631
Commit: 4818565467e6b847007dbb4032484a3efb6d091e
Parents: 66ab01b
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon Feb 13 08:51:51 2017 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Tue Feb 14 15:05:51 2017 -0500
----------------------------------------------------------------------
.../AbstractGremlinScriptEngineFactory.java | 118 +++++++++++++++++++
.../gremlin/jsr223/BindingsGremlinPlugin.java | 49 ++------
.../jsr223/DefaultBindingsCustomizer.java | 17 +--
.../DefaultGremlinScriptEngineManager.java | 43 ++++---
.../gremlin/jsr223/LazyBindingsCustomizer.java | 18 +--
.../GremlinGroovyScriptEngineFactory.java | 75 ++----------
.../jsr223/BindingsScriptEngineTest.java | 65 ++++++----
.../gremlin/jsr223/MockGremlinScriptEngine.java | 62 ++++++++++
.../jsr223/MockGremlinScriptEngineFactory.java | 51 ++++++++
...op.gremlin.jsr223.GremlinScriptEngineFactory | 1 +
.../gremlin/jsr223/bindings-init.groovy | 22 ++++
.../hadoop/jsr223/HadoopGremlinPlugin.java | 11 +-
.../hadoop/jsr223/HadoopGremlinPluginTest.java | 51 ++++++++
13 files changed, 415 insertions(+), 168 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/AbstractGremlinScriptEngineFactory.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/AbstractGremlinScriptEngineFactory.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/AbstractGremlinScriptEngineFactory.java
new file mode 100644
index 0000000..e07e884
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/AbstractGremlinScriptEngineFactory.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.tinkerpop.gremlin.jsr223;
+
+import org.apache.tinkerpop.gremlin.util.Gremlin;
+
+import javax.script.ScriptEngine;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A simple base implementation of the {@link GremlinScriptEngineFactory}.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public abstract class AbstractGremlinScriptEngineFactory implements GremlinScriptEngineFactory {
+
+ private final String engineName;
+ private final String languageName;
+ private final List<String> extensions;
+ private final List<String> mimeTypes;
+
+ protected GremlinScriptEngineManager manager;
+
+ public AbstractGremlinScriptEngineFactory(final String engineName, final String languageName,
+ final List<String> extensions, final List<String> mimeTypes) {
+ this.engineName = engineName;
+ this.languageName = languageName;
+ this.extensions = Collections.unmodifiableList(extensions);
+ this.mimeTypes = Collections.unmodifiableList(mimeTypes);
+ }
+
+ @Override
+ public void setCustomizerManager(final GremlinScriptEngineManager manager) {
+ this.manager = manager;
+ }
+
+ @Override
+ public String getEngineName() {
+ return engineName;
+ }
+
+ @Override
+ public String getEngineVersion() {
+ return Gremlin.version();
+ }
+
+ @Override
+ public List<String> getExtensions() {
+ return extensions;
+ }
+
+ @Override
+ public String getLanguageName() {
+ return languageName;
+ }
+
+ @Override
+ public String getLanguageVersion() {
+ return Gremlin.version();
+ }
+
+ @Override
+ public List<String> getMimeTypes() {
+ return mimeTypes;
+ }
+
+ @Override
+ public List<String> getNames() {
+ return Collections.singletonList(languageName);
+ }
+
+ @Override
+ public Object getParameter(final String key) {
+ if (key.equals(ScriptEngine.ENGINE)) {
+ return this.getEngineName();
+ } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {
+ return this.getEngineVersion();
+ } else if (key.equals(ScriptEngine.NAME)) {
+ return engineName;
+ } else if (key.equals(ScriptEngine.LANGUAGE)) {
+ return this.getLanguageName();
+ } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) {
+ return this.getLanguageVersion();
+ } else
+ return null;
+ }
+
+ /**
+ * Statements are concatenated together by a line feed.
+ */
+ @Override
+ public String getProgram(final String... statements) {
+ String program = "";
+
+ for (String statement : statements) {
+ program = program + statement + System.lineSeparator();
+ }
+
+ return program;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsGremlinPlugin.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsGremlinPlugin.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsGremlinPlugin.java
index 59304df..003f79d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsGremlinPlugin.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsGremlinPlugin.java
@@ -28,21 +28,13 @@ import java.util.Set;
import java.util.function.Supplier;
/**
- * A module that allows {@code Bindings} to be applied to a {@link GremlinScriptEngine}. The bindings are controled by
- * their {@code scope} which are determined by the {@code ScriptContext} values where "100" is {@code ENGINE_SCOPE}
- * (bindings apply to the current {@link GremlinScriptEngine}) and "200" is {@code GLOBAL_SCOPE} (bindings apply to the
- * engines created by the current {@link GremlinScriptEngineManager}.
+ * A plugin that allows {@code Bindings} to be applied to a {@link GremlinScriptEngine} at the time of creation.
+ * {@code Bindings} defined with this plugin will always be assigned as {@code ScriptContext.GLOBAL_SCOPE} and as such
+ * will be visible to all {@link GremlinScriptEngine} instances.
* <p/>
- * Note that bindings are applied in the following order:
- * <ol>
- * <li>The order in which the {@link GremlinScriptEngine} is requested from the {@link GremlinScriptEngineManager}</li>
- * <li>The order in which the {@code BindingsGremlinPlugin} instances are added to the {@link GremlinScriptEngineManager}</li>
- * </ol>
- * <p/>
- * Moreover, they will override one another within a scope and among scopes. For instance, {@code ENGINE_SCOPE} bindings
- * will override {@code GLOBAL_SCOPE}. Those bindings that are {@code GLOBAL_SCOPE} and applied to a single
- * {@link GremlinScriptEngine} via an {@link Builder#appliesTo} configuration will still appear present to all other
- * {@link GremlinScriptEngine} created by the {@link GremlinScriptEngineManager} that the plugin was bound to.
+ * Note that bindings are applied in the order in which the {@code BindingsGremlinPlugin} instances are added to the
+ * {@link GremlinScriptEngineManager}. Therefore if there are two plugins added and both include a variable called "x"
+ * then the value of "x" will be the equal to the value provided by the second plugin that overrides the first.
* <p/>
* This {@link GremlinPlugin} is not enabled for the {@code ServiceLoader}. It is designed to be instantiated manually.
*
@@ -52,17 +44,16 @@ public class BindingsGremlinPlugin extends AbstractGremlinPlugin {
private static final String NAME = "tinkerpop.bindings";
private BindingsGremlinPlugin(final Builder builder) {
- super(NAME, builder.appliesTo, new DefaultBindingsCustomizer(builder.bindings, builder.scope));
- }
-
- public BindingsGremlinPlugin(final Bindings bindings, final int scope) {
- super(NAME, new DefaultBindingsCustomizer(bindings, scope));
+ super(NAME, new DefaultBindingsCustomizer(builder.bindings));
}
- public BindingsGremlinPlugin(final Supplier<Bindings> bindingsSupplier, final int scope) {
- super(NAME, new LazyBindingsCustomizer(bindingsSupplier, scope));
+ BindingsGremlinPlugin(final Supplier<Bindings> bindingsSupplier) {
+ super(NAME, new LazyBindingsCustomizer(bindingsSupplier));
}
+ /**
+ * Builds a set of static bindings.
+ */
public static BindingsGremlinPlugin.Builder build() {
return new Builder();
}
@@ -70,30 +61,14 @@ public class BindingsGremlinPlugin extends AbstractGremlinPlugin {
public static final class Builder {
private Bindings bindings = new SimpleBindings();
- private int scope = ScriptContext.ENGINE_SCOPE;
- private final Set<String> appliesTo = new HashSet<>();
private Builder() {}
- /**
- * The name of the {@link GremlinScriptEngine} that this module will apply to. Setting no values here will
- * make the module available to all the engines.
- */
- public BindingsGremlinPlugin.Builder appliesTo(final Collection<String> scriptEngineName) {
- this.appliesTo.addAll(scriptEngineName);
- return this;
- }
-
public Builder bindings(final Map<String, Object> bindings) {
this.bindings = new SimpleBindings(bindings);
return this;
}
- public Builder scope(final int scope) {
- this.scope = scope;
- return this;
- }
-
public BindingsGremlinPlugin create() {
return new BindingsGremlinPlugin(this);
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultBindingsCustomizer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultBindingsCustomizer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultBindingsCustomizer.java
index cee5182..59d8230 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultBindingsCustomizer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultBindingsCustomizer.java
@@ -22,10 +22,7 @@ import javax.script.Bindings;
import javax.script.ScriptContext;
/**
- * Default implementation of the {@link BindingsCustomizer}. If this customizer is applied directly to a
- * {@link GremlinScriptEngine} it will not apply {@code GLOBAL_SCOPE} bindings. Those can only be applied if the
- * customizer is applied via the {@link GremlinScriptEngineManager} (which would do so through the
- * {@link BindingsGremlinPlugin}.
+ * Default implementation of the {@link BindingsCustomizer} which adds bindings to the {@code ScriptContext.GLOBAL_SCOPE}.
*
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
@@ -35,13 +32,19 @@ public class DefaultBindingsCustomizer implements BindingsCustomizer {
private final int scope;
/**
- * Creates a new object with {@code ScriptContext.ENGINE_SCOPE}.
+ * Creates a new object with {@code ScriptContext.GLOBAL_SCOPE}.
*/
public DefaultBindingsCustomizer(final Bindings bindings) {
- this(bindings, ScriptContext.ENGINE_SCOPE);
+ this(bindings, ScriptContext.GLOBAL_SCOPE);
}
- public DefaultBindingsCustomizer(final Bindings bindings, final int scope) {
+ /**
+ * Creates a new object with a specified scope. There really can't be anything other than a {@code GLOBAL_SCOPE}
+ * specification so this constructor isn't public at the moment. Assigning to {@code ENGINE_SCOPE} is useless
+ * because it is the nature of the {@code ScriptEngine} to override that scope with {@code Bindings} supplied at
+ * the time of execution.
+ */
+ DefaultBindingsCustomizer(final Bindings bindings, final int scope) {
this.bindings = bindings;
this.scope = scope;
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultGremlinScriptEngineManager.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultGremlinScriptEngineManager.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultGremlinScriptEngineManager.java
index 01b4957..d63147d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultGremlinScriptEngineManager.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/DefaultGremlinScriptEngineManager.java
@@ -18,6 +18,9 @@
*/
package org.apache.tinkerpop.gremlin.jsr223;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import javax.script.Bindings;
import javax.script.ScriptContext;
import java.security.AccessController;
@@ -63,7 +66,7 @@ import java.util.stream.Stream;
*/
public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineManager {
- private static final boolean DEBUG = false;
+ private static final Logger logger = LoggerFactory.getLogger(DefaultGremlinScriptEngineManager.class);
/**
* Set of script engine factories discovered.
@@ -222,7 +225,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
try {
return createGremlinScriptEngine(spi);
} catch (Exception exp) {
- if (DEBUG) exp.printStackTrace();
+ logger.error(String.format("Could not create GremlinScriptEngine for %s", shortName), exp);
}
}
@@ -231,7 +234,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
try {
names = spi.getNames();
} catch (Exception exp) {
- if (DEBUG) exp.printStackTrace();
+ logger.error("Could not get GremlinScriptEngine names", exp);
}
if (names != null) {
@@ -240,7 +243,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
try {
return createGremlinScriptEngine(spi);
} catch (Exception exp) {
- if (DEBUG) exp.printStackTrace();
+ logger.error(String.format("Could not create GremlinScriptEngine for %s", shortName), exp);
}
}
}
@@ -269,7 +272,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
try {
return createGremlinScriptEngine(spi);
} catch (Exception exp) {
- if (DEBUG) exp.printStackTrace();
+ logger.error(String.format("Could not create GremlinScriptEngine for %s", extension), exp);
}
}
@@ -278,7 +281,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
try {
exts = spi.getExtensions();
} catch (Exception exp) {
- if (DEBUG) exp.printStackTrace();
+ logger.error("Could not get GremlinScriptEngine extensions", exp);
}
if (exts == null) continue;
for (String ext : exts) {
@@ -286,7 +289,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
try {
return createGremlinScriptEngine(spi);
} catch (Exception exp) {
- if (DEBUG) exp.printStackTrace();
+ logger.error(String.format("Could not create GremlinScriptEngine for %s", extension), exp);
}
}
}
@@ -314,7 +317,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
try {
return createGremlinScriptEngine(spi);
} catch (Exception exp) {
- if (DEBUG) exp.printStackTrace();
+ logger.error(String.format("Could not create GremlinScriptEngine for %s", mimeType), exp);
}
}
@@ -323,7 +326,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
try {
types = spi.getMimeTypes();
} catch (Exception exp) {
- if (DEBUG) exp.printStackTrace();
+ logger.error("Could not get GremlinScriptEngine mimetypes", exp);
}
if (types == null) continue;
for (String type : types) {
@@ -331,7 +334,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
try {
return createGremlinScriptEngine(spi);
} catch (Exception exp) {
- if (DEBUG) exp.printStackTrace();
+ logger.error(String.format("Could not create GremlinScriptEngine for %s", mimeType), exp);
}
}
}
@@ -409,9 +412,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
(PrivilegedAction<ServiceLoader<GremlinScriptEngineFactory>>) () -> getServiceLoader(loader));
itty = sl.iterator();
} catch (ServiceConfigurationError err) {
- System.err.println("Can't find GremlinScriptEngineFactory providers: " +
- err.getMessage());
- if (DEBUG) err.printStackTrace();
+ logger.error("Can't find GremlinScriptEngineFactory providers: " + err.getMessage(), err);
// do not throw any exception here. user may want to manager their own factories using this manager
// by explicit registration (by registerXXX) methods.
@@ -425,15 +426,11 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
factory.setCustomizerManager(this);
engineSpis.add(factory);
} catch (ServiceConfigurationError err) {
- System.err.println("GremlinScriptEngineManager providers.next(): "
- + err.getMessage());
- if (DEBUG) err.printStackTrace();
+ logger.error("GremlinScriptEngineManager providers.next(): " + err.getMessage(), err);
}
}
} catch (ServiceConfigurationError err) {
- System.err.println("GremlinScriptEngineManager providers.hasNext(): "
- + err.getMessage());
- if (DEBUG) err.printStackTrace();
+ logger.error("GremlinScriptEngineManager providers.hasNext(): " + err.getMessage(), err);
// do not throw any exception here. user may want to manage their own factories using this manager
// by explicit registration (by registerXXX) methods.
}
@@ -450,13 +447,14 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
.forEach(bc -> globalScope.putAll(bc.getBindings()));
engine.setBindings(getBindings(), ScriptContext.GLOBAL_SCOPE);
- // merge in bindings that are marked with engine scope. these get applied to only those GremlinScriptEngine
- // instances that are of this gremlin language
+ // merge in bindings that are marked with engine scope. there typically won't be any of these but it's just
+ // here for completeness. bindings will typically apply with global scope only as engine scope will generally
+ // be overridden at the time of eval() with the bindings that are supplied to it
getCustomizers(spi.getEngineName()).stream()
.filter(p -> p instanceof BindingsCustomizer)
.map(p -> ((BindingsCustomizer) p))
.filter(bc -> bc.getScope() == ScriptContext.ENGINE_SCOPE)
- .forEach(bc -> engine.setBindings(bc.getBindings(), ScriptContext.ENGINE_SCOPE));
+ .forEach(bc -> engine.getBindings(ScriptContext.ENGINE_SCOPE).putAll(bc.getBindings()));
final List<ScriptCustomizer> scriptCustomizers = getCustomizers(spi.getEngineName()).stream()
.filter(p -> p instanceof ScriptCustomizer)
@@ -475,6 +473,7 @@ public class DefaultGremlinScriptEngineManager implements GremlinScriptEngineMan
throw new IllegalStateException(ex);
}
});
+
return engine;
}
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/LazyBindingsCustomizer.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/LazyBindingsCustomizer.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/LazyBindingsCustomizer.java
index 8feb361..bc4c794 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/LazyBindingsCustomizer.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/LazyBindingsCustomizer.java
@@ -23,10 +23,8 @@ import javax.script.ScriptContext;
import java.util.function.Supplier;
/**
- * A customizer implementation that provides bindings to a {@link GremlinScriptEngine}. If this customizer is applied
- * directly to a {@link GremlinScriptEngine} it will not apply {@code GLOBAL_SCOPE} bindings. Those can only be applied
- * if the customizer is applied via the {@link GremlinScriptEngineManager} (which would do so through the
- * {@link BindingsGremlinPlugin}.
+ * A customizer implementation that provides bindings to a {@link GremlinScriptEngine} in the
+ * {@code ScriptContext.GLOBAL_SCOPE}.
*
* @author Stephen Mallette (http://stephen.genoprime.com)
*/
@@ -36,13 +34,19 @@ public class LazyBindingsCustomizer implements BindingsCustomizer {
private final int scope;
/**
- * Creates a new object with {@code ScriptContext.ENGINE_SCOPE}.
+ * Creates a new object with {@code ScriptContext.GLOBAL_SCOPE}.
*/
public LazyBindingsCustomizer(final Supplier<Bindings> bindingsSupplier) {
- this(bindingsSupplier, ScriptContext.ENGINE_SCOPE);
+ this(bindingsSupplier, ScriptContext.GLOBAL_SCOPE);
}
- public LazyBindingsCustomizer(final Supplier<Bindings> bindingsSupplier, final int scope) {
+ /**
+ * Creates a new object with a specified scope. There really can't be anything other than a {@code GLOBAL_SCOPE}
+ * specification so this constructor isn't public at the moment. Assigning to {@code ENGINE_SCOPE} is useless
+ * because it is the nature of the {@code ScriptEngine} to override that scope with {@code Bindings} supplied at
+ * the time of execution.
+ */
+ LazyBindingsCustomizer(final Supplier<Bindings> bindingsSupplier, final int scope) {
this.bindingsSupplier = bindingsSupplier;
this.scope = scope;
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineFactory.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineFactory.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineFactory.java
index 8e5defb..cd7e2fd 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineFactory.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/jsr223/GremlinGroovyScriptEngineFactory.java
@@ -18,6 +18,7 @@
*/
package org.apache.tinkerpop.gremlin.groovy.jsr223;
+import org.apache.tinkerpop.gremlin.jsr223.AbstractGremlinScriptEngineFactory;
import org.apache.tinkerpop.gremlin.jsr223.Customizer;
import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngine;
import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory;
@@ -29,45 +30,20 @@ import java.util.Collections;
import java.util.List;
/**
+ * A {@link GremlinScriptEngineFactory} implementation that creates {@link GremlinGroovyScriptEngine} instances.
+ *
* @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
*/
-public class GremlinGroovyScriptEngineFactory implements GremlinScriptEngineFactory {
+public class GremlinGroovyScriptEngineFactory extends AbstractGremlinScriptEngineFactory {
private static final String ENGINE_NAME = "gremlin-groovy";
private static final String LANGUAGE_NAME = "gremlin-groovy";
private static final String PLAIN = "plain";
private static final List<String> EXTENSIONS = Collections.singletonList("groovy");
- private GremlinScriptEngineManager manager;
-
- @Override
- public void setCustomizerManager(final GremlinScriptEngineManager manager) {
- this.manager = manager;
- }
-
- @Override
- public String getEngineName() {
- return ENGINE_NAME;
- }
-
- @Override
- public String getEngineVersion() {
- return Gremlin.version();
- }
-
- @Override
- public List<String> getExtensions() {
- return EXTENSIONS;
- }
-
- @Override
- public String getLanguageName() {
- return LANGUAGE_NAME;
- }
-
- @Override
- public String getLanguageVersion() {
- return Gremlin.version();
+ public GremlinGroovyScriptEngineFactory() {
+ super(ENGINE_NAME, LANGUAGE_NAME, EXTENSIONS, Collections.singletonList(PLAIN));
}
@Override
@@ -76,48 +52,11 @@ public class GremlinGroovyScriptEngineFactory implements GremlinScriptEngineFact
}
@Override
- public List<String> getMimeTypes() {
- return Collections.singletonList(PLAIN);
- }
-
- @Override
- public List<String> getNames() {
- return Collections.singletonList(LANGUAGE_NAME);
- }
-
- @Override
public String getOutputStatement(final String toDisplay) {
return "println " + toDisplay;
}
@Override
- public Object getParameter(final String key) {
- if (key.equals(ScriptEngine.ENGINE)) {
- return this.getEngineName();
- } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {
- return this.getEngineVersion();
- } else if (key.equals(ScriptEngine.NAME)) {
- return ENGINE_NAME;
- } else if (key.equals(ScriptEngine.LANGUAGE)) {
- return this.getLanguageName();
- } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) {
- return this.getLanguageVersion();
- } else
- return null;
- }
-
- @Override
- public String getProgram(final String... statements) {
- String program = "";
-
- for (String statement : statements) {
- program = program + statement + "\n";
- }
-
- return program;
- }
-
- @Override
public GremlinScriptEngine getScriptEngine() {
final List<Customizer> customizers = manager.getCustomizers(ENGINE_NAME);
return (customizers.isEmpty()) ? new GremlinGroovyScriptEngine() :
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsScriptEngineTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsScriptEngineTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsScriptEngineTest.java
index e02b834..8d90fec 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsScriptEngineTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/BindingsScriptEngineTest.java
@@ -18,15 +18,20 @@
*/
package org.apache.tinkerpop.gremlin.jsr223;
+import org.apache.tinkerpop.gremlin.TestHelper;
import org.junit.Test;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptException;
import javax.script.SimpleBindings;
-import java.util.Collections;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
import static org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineSuite.ENGINE_TO_TEST;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
/**
@@ -42,9 +47,7 @@ public class BindingsScriptEngineTest {
b.put("y", 2);
manager.addPlugin(BindingsGremlinPlugin.build().
- bindings(b).
- scope(ScriptContext.GLOBAL_SCOPE).
- appliesTo(Collections.singletonList(ENGINE_TO_TEST)).create());
+ bindings(b).create());
final GremlinScriptEngine engine = manager.getEngineByName(ENGINE_TO_TEST);
assertEquals(1, engine.eval("x"));
@@ -52,44 +55,58 @@ public class BindingsScriptEngineTest {
}
@Test
- public void shouldIncludeEngineBindings() throws ScriptException {
- final GremlinScriptEngineManager manager = new DefaultGremlinScriptEngineManager();
- final Bindings b = new SimpleBindings();
- b.put("x", 1);
- b.put("y", 2);
+ public void shouldRemoveGlobalBindings() throws Exception {
+ final DefaultGremlinScriptEngineManager manager = new DefaultGremlinScriptEngineManager();
+ manager.put("x", 100);
- manager.addPlugin(BindingsGremlinPlugin.build().
- bindings(b).
- scope(ScriptContext.ENGINE_SCOPE).
- appliesTo(Collections.singletonList(ENGINE_TO_TEST)).create());
+ final GremlinScriptEngine engine1 = manager.getEngineByName(ENGINE_TO_TEST);
+ assertThat(engine1.getBindings(ScriptContext.GLOBAL_SCOPE).size(), is(1));
+ assertEquals(101, (int) engine1.eval("x+1"));
+
+ manager.getBindings().remove("x");
+ final GremlinScriptEngine engine2 = manager.getEngineByName(ENGINE_TO_TEST);
+ assertThat(engine2.getBindings(ScriptContext.GLOBAL_SCOPE).size(), is(0));
+ }
+ @Test
+ public void shouldAddLazyGlobalBindingsViaPlugin() throws Exception {
+ final Bindings bindings = new SimpleBindings();
+ bindings.put("x", 100);
+ final BindingsGremlinPlugin plugin = new BindingsGremlinPlugin(() -> bindings);
+
+ final DefaultGremlinScriptEngineManager manager = new DefaultGremlinScriptEngineManager();
+ manager.addPlugin(plugin);
final GremlinScriptEngine engine = manager.getEngineByName(ENGINE_TO_TEST);
- assertEquals(1, engine.eval("x"));
- assertEquals(2, engine.eval("y"));
+ assertThat(engine.getBindings(ScriptContext.GLOBAL_SCOPE).size(), is(1));
+ assertEquals(101, (int) engine.eval("x+1"));
}
@Test
- public void shouldIncludeEngineBindingsToOverrideGlobalBindings() throws ScriptException {
+ public void shouldExtractGlobalBindingsAfterScriptExecution() throws Exception {
final GremlinScriptEngineManager manager = new DefaultGremlinScriptEngineManager();
final Bindings b1 = new SimpleBindings();
b1.put("x", 1);
b1.put("y", 2);
- manager.addPlugin(BindingsGremlinPlugin.build().
- bindings(b1).
- scope(ScriptContext.GLOBAL_SCOPE).
- appliesTo(Collections.singletonList(ENGINE_TO_TEST)).create());
+ manager.addPlugin(BindingsGremlinPlugin.build().bindings(b1).create());
final Bindings b2 = new SimpleBindings();
b2.put("x", 100);
b2.put("y", 200);
- manager.addPlugin(BindingsGremlinPlugin.build().
- bindings(b2).
- scope(ScriptContext.ENGINE_SCOPE).
- appliesTo(Collections.singletonList(ENGINE_TO_TEST)).create());
+ manager.addPlugin(BindingsGremlinPlugin.build().bindings(b2).create());
+
+ final File scriptFile = TestHelper.generateTempFileFromResource(BindingsScriptEngineTest.class, "bindings-init.groovy", ".groovy");
+ final List<String> files = new ArrayList<>();
+ files.add(scriptFile.getAbsolutePath());
+ manager.addPlugin(ScriptFileGremlinPlugin.build().files(files).create());
final GremlinScriptEngine engine = manager.getEngineByName(ENGINE_TO_TEST);
assertEquals(100, engine.eval("x"));
assertEquals(200, engine.eval("y"));
+ assertEquals(300, engine.eval("z"));
+ assertEquals(600, engine.eval("addItUp(z, addItUp(x,y))"));
+
+ assertEquals(300, engine.getBindings(ScriptContext.GLOBAL_SCOPE).get("z"));
+ assertThat(engine.getBindings(ScriptContext.ENGINE_SCOPE).containsKey("z"), is(false));
}
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/MockGremlinScriptEngine.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/MockGremlinScriptEngine.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/MockGremlinScriptEngine.java
new file mode 100644
index 0000000..ac0c94f
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/MockGremlinScriptEngine.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.tinkerpop.gremlin.jsr223;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Bytecode;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+
+import javax.script.AbstractScriptEngine;
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptException;
+import javax.script.SimpleBindings;
+import java.io.Reader;
+
+/**
+ * This is a "do nothing" implementation of the {@link GremlinScriptEngine} which can be used to help test plugin
+ * implementations which don't have reference to a {@link GremlinScriptEngine} as a dependency.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class MockGremlinScriptEngine extends AbstractScriptEngine implements GremlinScriptEngine {
+ @Override
+ public GremlinScriptEngineFactory getFactory() {
+ return new MockGremlinScriptEngineFactory();
+ }
+
+ @Override
+ public Traversal.Admin eval(final Bytecode bytecode, final Bindings bindings) throws ScriptException {
+ return null;
+ }
+
+ @Override
+ public Object eval(final String script, final ScriptContext context) throws ScriptException {
+ return null;
+ }
+
+ @Override
+ public Object eval(final Reader reader, final ScriptContext context) throws ScriptException {
+ return null;
+ }
+
+ @Override
+ public Bindings createBindings() {
+ return new SimpleBindings();
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/MockGremlinScriptEngineFactory.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/MockGremlinScriptEngineFactory.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/MockGremlinScriptEngineFactory.java
new file mode 100644
index 0000000..b4d0732
--- /dev/null
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/jsr223/MockGremlinScriptEngineFactory.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.tinkerpop.gremlin.jsr223;
+
+import java.util.Collections;
+
+/**
+ * This is a "do nothing" implementation of the {@link GremlinScriptEngineFactory} which can be used to help test plugin
+ * implementations which don't have reference to a {@link GremlinScriptEngine} as a dependency.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class MockGremlinScriptEngineFactory extends AbstractGremlinScriptEngineFactory {
+
+ public static final String ENGINE_NAME = "gremlin-mock";
+
+ public MockGremlinScriptEngineFactory() {
+ super(ENGINE_NAME, ENGINE_NAME, Collections.singletonList("script"), Collections.singletonList("plain"));
+ }
+
+ @Override
+ public GremlinScriptEngine getScriptEngine() {
+ return new MockGremlinScriptEngine();
+ }
+
+ @Override
+ public String getMethodCallSyntax(final String obj, final String m, final String... args) {
+ return null;
+ }
+
+ @Override
+ public String getOutputStatement(final String toDisplay) {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/gremlin-test/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory b/gremlin-test/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
new file mode 100644
index 0000000..819f04f
--- /dev/null
+++ b/gremlin-test/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineFactory
@@ -0,0 +1 @@
+org.apache.tinkerpop.gremlin.jsr223.MockGremlinScriptEngineFactory
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/jsr223/bindings-init.groovy
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/jsr223/bindings-init.groovy b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/jsr223/bindings-init.groovy
new file mode 100644
index 0000000..e924c13
--- /dev/null
+++ b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/jsr223/bindings-init.groovy
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.
+ */
+
+def addItUp(x, y) { x + y }
+def globals = [:]
+globals << [z : addItUp(x,y)]
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/jsr223/HadoopGremlinPlugin.java
----------------------------------------------------------------------
diff --git a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/jsr223/HadoopGremlinPlugin.java b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/jsr223/HadoopGremlinPlugin.java
index 0c9c287..581920d 100644
--- a/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/jsr223/HadoopGremlinPlugin.java
+++ b/hadoop-gremlin/src/main/java/org/apache/tinkerpop/gremlin/hadoop/jsr223/HadoopGremlinPlugin.java
@@ -77,11 +77,10 @@ public final class HadoopGremlinPlugin extends AbstractGremlinPlugin {
private static final ImportCustomizer imports;
- private static final Set<String> appliesTo = new HashSet<>(Collections.singletonList("gremlin-groovy"));
+ private static final Set<String> appliesTo = Collections.emptySet();
static {
try {
- // TODO: most of the imports here were wildcarded, but we dont' allow that anymore - needs review
imports = DefaultImportCustomizer.build()
.addClassImports(
Configuration.class,
@@ -131,7 +130,9 @@ public final class HadoopGremlinPlugin extends AbstractGremlinPlugin {
}
}
- public HadoopGremlinPlugin() {
+ private static final HadoopGremlinPlugin plugin = new HadoopGremlinPlugin();
+
+ private HadoopGremlinPlugin() {
super(NAME, appliesTo, imports, bindings, new HadoopConsoleCustomizer());
}
@@ -150,6 +151,10 @@ public final class HadoopGremlinPlugin extends AbstractGremlinPlugin {
return true;
}
+ public static HadoopGremlinPlugin instance() {
+ return plugin;
+ }
+
private static class HadoopConsoleCustomizer implements ConsoleCustomizer {
@Override
public RemoteAcceptor getRemoteAcceptor(final GremlinShellEnvironment environment) {
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/48185654/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/jsr223/HadoopGremlinPluginTest.java
----------------------------------------------------------------------
diff --git a/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/jsr223/HadoopGremlinPluginTest.java b/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/jsr223/HadoopGremlinPluginTest.java
new file mode 100644
index 0000000..167c834
--- /dev/null
+++ b/hadoop-gremlin/src/test/java/org/apache/tinkerpop/gremlin/hadoop/jsr223/HadoopGremlinPluginTest.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.tinkerpop.gremlin.hadoop.jsr223;
+
+import org.apache.tinkerpop.gremlin.hadoop.structure.io.FileSystemStorage;
+import org.apache.tinkerpop.gremlin.jsr223.DefaultGremlinScriptEngineManager;
+import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngine;
+import org.apache.tinkerpop.gremlin.jsr223.GremlinScriptEngineManager;
+import org.apache.tinkerpop.gremlin.jsr223.MockGremlinScriptEngineFactory;
+import org.junit.Test;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class HadoopGremlinPluginTest {
+
+ @Test
+ public void shouldAddBindingsForFileSystem() {
+ final GremlinScriptEngineManager manager = new DefaultGremlinScriptEngineManager();
+ manager.addPlugin(HadoopGremlinPlugin.instance());
+ final GremlinScriptEngine engine = manager.getEngineByName(MockGremlinScriptEngineFactory.ENGINE_NAME);
+ final Bindings b = engine.getBindings(ScriptContext.GLOBAL_SCOPE);
+ assertThat(b.containsKey("hdfs"), is(true));
+ assertThat(b.containsKey("fs"), is(true));
+ assertThat(b.get("hdfs"), instanceOf(FileSystemStorage.class));
+ assertThat(b.get("fs"), instanceOf(FileSystemStorage.class));
+ }
+}