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/25 16:19:19 UTC

[08/36] tinkerpop git commit: Added more tests for the new plugin system.

Added more tests for the new plugin system.

Deprecated GephiTraversalVisualizationStrategy and moved it to the jsr223 package. CTR


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/d62495b2
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/d62495b2
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/d62495b2

Branch: refs/heads/TINKERPOP-1612
Commit: d62495b295d5412c0110a36e7328aafb7702e28f
Parents: 0141cfc
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Sat Feb 25 08:12:59 2017 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Sat Feb 25 08:12:59 2017 -0500

----------------------------------------------------------------------
 .../console/jsr223/GephiRemoteAcceptor.groovy   |   1 -
 .../GephiTraversalVisualizationStrategy.groovy  | 121 +++++++++++++
 .../GephiTraversalVisualizationStrategy.groovy  |   2 +
 .../groovy/plugin/GremlinPluginAdapterTest.java |   3 -
 .../AbstractGremlinServerIntegrationTest.java   |  63 +++++++
 .../DriverRemoteAcceptorIntegrateTest.java      | 158 ++++++++++++++++
 .../jsr223/DriverRemoteAcceptorTest.java        | 140 +++++++++++++++
 .../GephiRemoteAcceptorIntegrateTest.java       | 178 +++++++++++++++++++
 .../MockGroovyGremlinShellEnvironment.java      |  64 +++++++
 .../jsr223/UtilitiesGremlinPluginTest.java      |  70 ++++++++
 .../jsr223/gremlin-server-integration.yaml      |  54 ++++++
 .../gremlin/console/jsr223/remote.yaml          |  20 +++
 .../console/jsr223/script-customizer-1.groovy   |   3 +
 .../console/jsr223/script-customizer-2.groovy   |   2 +
 .../console/jsr223/tinkergraph-empty.properties |  18 ++
 .../gremlin/groovy/plugin/RemoteException.java  |   2 +-
 pom.xml                                         |   1 +
 17 files changed, 895 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptor.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptor.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptor.groovy
index 4e41fa4..4d023dd 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptor.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptor.groovy
@@ -28,7 +28,6 @@ import org.apache.http.entity.StringEntity
 import org.apache.http.impl.client.CloseableHttpClient
 import org.apache.http.impl.client.HttpClients
 import org.apache.http.util.EntityUtils
-import org.apache.tinkerpop.gremlin.console.plugin.GephiTraversalVisualizationStrategy
 import org.apache.tinkerpop.gremlin.jsr223.console.GremlinShellEnvironment
 import org.apache.tinkerpop.gremlin.jsr223.console.RemoteAcceptor
 import org.apache.tinkerpop.gremlin.jsr223.console.RemoteException

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiTraversalVisualizationStrategy.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiTraversalVisualizationStrategy.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiTraversalVisualizationStrategy.groovy
new file mode 100644
index 0000000..fe1013a
--- /dev/null
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiTraversalVisualizationStrategy.groovy
@@ -0,0 +1,121 @@
+/*
+ * 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.console.jsr223
+
+import groovy.transform.CompileStatic
+import org.apache.tinkerpop.gremlin.process.traversal.Step
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.HasStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeOtherVertexStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.EdgeVertexStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.VertexStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.AggregateStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.LambdaSideEffectStep
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper
+import org.apache.tinkerpop.gremlin.structure.Vertex
+
+import java.util.stream.Collectors
+
+/**
+ * A strategy that works in conjuction with the {@link org.apache.tinkerpop.gremlin.console.plugin.GephiRemoteAcceptor} to automatically inject visualization
+ * steps after "vertex" steps to show the vertices traversed for a step.  If the traversal was evaluated in the
+ * console normally then the visualization strategy will not be applied.  It must be {@code :submit} to the
+ * console for the strategy to be applied.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@CompileStatic
+class GephiTraversalVisualizationStrategy extends AbstractTraversalStrategy<TraversalStrategy.FinalizationStrategy>
+        implements TraversalStrategy.FinalizationStrategy {
+
+    private static final Set<Class<? extends TraversalStrategy.FinalizationStrategy>> POSTS = new HashSet<>();
+
+    static {
+        POSTS.add(ProfileStrategy.class);
+    }
+
+    private final GephiRemoteAcceptor acceptor
+
+    private final String sideEffectKey = "viz-" + UUID.randomUUID()
+
+    GephiTraversalVisualizationStrategy(final GephiRemoteAcceptor acceptor) {
+        this.acceptor = acceptor
+    }
+
+    @Override
+    void apply(final Traversal.Admin<?, ?> traversal) {
+        if (TraversalHelper.onGraphComputer(traversal))
+            return
+
+        // only apply these strategies if the traversal was :submit to the acceptor - otherwise process as usual
+        if (acceptor.traversalSubmittedForViz) {
+            final List<GraphStep> graphSteps = TraversalHelper.getStepsOfAssignableClass(GraphStep.class, traversal)
+            final List<VertexStep> vertexSteps = TraversalHelper.getStepsOfAssignableClass(VertexStep.class, traversal)
+
+            def List<Step> addAfter = new ArrayList<>()
+            addAfter.addAll(TraversalHelper.getStepsOfAssignableClass(EdgeOtherVertexStep.class, traversal))
+            addAfter.addAll(TraversalHelper.getStepsOfAssignableClass(EdgeVertexStep.class, traversal))
+            addAfter.addAll(vertexSteps.stream().filter { it.returnsVertex() }.collect(Collectors.toList()))
+            addAfter.addAll(graphSteps.stream().filter { it.returnsVertex() }.collect(Collectors.toList()))
+
+            // decay all vertices and visit each one to update their colors to the brightest
+            addAfter.each { Step s ->
+                TraversalHelper.insertAfterStep(new LambdaSideEffectStep(traversal, { Traverser traverser ->
+                    final BulkSet<Vertex> vertices = ((BulkSet<Vertex>) traverser.sideEffects(sideEffectKey))
+                    if (!vertices.isEmpty()) {
+                        acceptor.updateVisitedVertices()
+                        vertices.forEach { Vertex v, Long l -> acceptor.visitVertexInGephi(v) }
+                        vertices.clear()
+                        Thread.sleep(acceptor.vizStepDelay)
+                    }
+                }), s, traversal)
+                TraversalHelper.insertAfterStep(new AggregateStep(traversal, sideEffectKey), s, traversal)
+            }
+
+            // decay all vertices except those that made it through the filter - "this way you can watch
+            // the Gremlins dying" - said daniel kuppitz. can't do this easily with generic FilterStep as
+            // it creates odd behaviors when used with loop (extra decay that probably shouldn't be there.
+            // todo: can this be better? maybe we shouldn't do this at all
+            TraversalHelper.getStepsOfAssignableClass(HasStep.class, traversal).each { HasStep s ->
+                TraversalHelper.insertAfterStep(new LambdaSideEffectStep(traversal, { Traverser traverser ->
+                    final BulkSet<Object> objects = ((BulkSet<Object>) traverser.sideEffects(sideEffectKey))
+                    if (!objects.isEmpty()) {
+                        final List<String> vertices = objects.findAll { Object o -> o instanceof Vertex }
+                                .collect { Object o -> ((Vertex) o).id().toString() }
+                        acceptor.updateVisitedVertices(vertices)
+                        objects.clear()
+                        Thread.sleep(acceptor.vizStepDelay)
+                    }
+                }), s, traversal)
+                TraversalHelper.insertAfterStep(new AggregateStep(traversal, sideEffectKey), s, traversal)
+            }
+        }
+    }
+
+    @Override
+    public Set<Class<? extends TraversalStrategy.FinalizationStrategy>> applyPost() {
+        return POSTS;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiTraversalVisualizationStrategy.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiTraversalVisualizationStrategy.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiTraversalVisualizationStrategy.groovy
index 319500e..c19de06 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiTraversalVisualizationStrategy.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiTraversalVisualizationStrategy.groovy
@@ -45,8 +45,10 @@ import java.util.stream.Collectors
  * console for the strategy to be applied.
  *
  * @author Stephen Mallette (http://stephen.genoprime.com)
+ * @deprecated As of release 3.2.5, replaced by {@link org.apache.tinkerpop.gremlin.console.jsr223.GephiTraversalVisualizationStrategy}
  */
 @CompileStatic
+@Deprecated
 class GephiTraversalVisualizationStrategy extends AbstractTraversalStrategy<TraversalStrategy.FinalizationStrategy>
         implements TraversalStrategy.FinalizationStrategy {
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GremlinPluginAdapterTest.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GremlinPluginAdapterTest.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GremlinPluginAdapterTest.java
index 58b1d39..dfc9006 100644
--- a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GremlinPluginAdapterTest.java
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GremlinPluginAdapterTest.java
@@ -23,10 +23,8 @@ import org.apache.tinkerpop.gremlin.console.plugin.PluggedIn;
 import org.apache.tinkerpop.gremlin.jsr223.BindingsCustomizer;
 import org.apache.tinkerpop.gremlin.jsr223.Customizer;
 import org.apache.tinkerpop.gremlin.jsr223.DefaultBindingsCustomizer;
-import org.apache.tinkerpop.gremlin.jsr223.DefaultScriptCustomizer;
 import org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin;
 import org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin;
-import org.apache.tinkerpop.gremlin.jsr223.ScriptCustomizer;
 import org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin;
 import org.junit.Test;
 
@@ -36,7 +34,6 @@ import java.io.File;
 import java.time.DayOfWeek;
 import java.time.temporal.TemporalAccessor;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/AbstractGremlinServerIntegrationTest.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/AbstractGremlinServerIntegrationTest.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/AbstractGremlinServerIntegrationTest.java
new file mode 100644
index 0000000..1bf9193
--- /dev/null
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/AbstractGremlinServerIntegrationTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.console.jsr223;
+
+import org.apache.tinkerpop.gremlin.server.GremlinServer;
+import org.apache.tinkerpop.gremlin.server.Settings;
+import org.junit.After;
+import org.junit.Before;
+
+import java.io.InputStream;
+
+/**
+ * Starts and stops an instance for each executed test.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public abstract class AbstractGremlinServerIntegrationTest {
+    private GremlinServer server;
+
+    public Settings overrideSettings(final Settings settings) {
+        return settings;
+    }
+
+    public InputStream getSettingsInputStream() {
+        return AbstractGremlinServerIntegrationTest.class.getResourceAsStream("gremlin-server-integration.yaml");
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        final InputStream stream = getSettingsInputStream();
+        final Settings settings = Settings.read(stream);
+
+        final Settings overridenSettings = overrideSettings(settings);
+        this.server = new GremlinServer(overridenSettings);
+
+        server.start().join();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        stopServer();
+    }
+
+    public void stopServer() throws Exception {
+        server.stop().join();
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorIntegrateTest.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorIntegrateTest.java
new file mode 100644
index 0000000..f794c61
--- /dev/null
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorIntegrateTest.java
@@ -0,0 +1,158 @@
+/*
+ * 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.console.jsr223;
+
+import org.apache.tinkerpop.gremlin.TestHelper;
+import org.apache.tinkerpop.gremlin.driver.Result;
+import org.apache.tinkerpop.gremlin.jsr223.console.GremlinShellEnvironment;
+import org.apache.tinkerpop.gremlin.server.Settings;
+import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
+import org.codehaus.groovy.tools.shell.Groovysh;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class DriverRemoteAcceptorIntegrateTest extends AbstractGremlinServerIntegrationTest {
+    private final Groovysh groovysh = new Groovysh();
+    private DriverRemoteAcceptor acceptor;
+
+    @Rule
+    public TestName name = new TestName();
+
+    /**
+     * Configure specific Gremlin Server settings for specific tests.
+     */
+    @Override
+    public Settings overrideSettings(final Settings settings) {
+        try {
+            final String tinkerGraphConfig = TestHelper.generateTempFileFromResource(this.getClass(), "tinkergraph-empty.properties", ".tmp").getAbsolutePath();
+            settings.graphs.put("g", tinkerGraphConfig);
+            return settings;
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    @Before
+    public void before() throws Exception {
+        final GremlinShellEnvironment env = new MockGroovyGremlinShellEnvironment(groovysh);
+        acceptor = new DriverRemoteAcceptor(env);
+    }
+
+    @After
+    public void after() {
+        try {
+            acceptor.close();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    @Test
+    public void shouldConnect() throws Exception {
+        assertThat(acceptor.connect(Collections.singletonList(TestHelper.generateTempFileFromResource(this.getClass(), "remote.yaml", ".tmp").getAbsolutePath())).toString(), startsWith("Configured "));
+    }
+
+    @Test
+    public void shouldConnectAndSubmitSession() throws Exception {
+        assertThat(acceptor.connect(Arrays.asList(TestHelper.generateTempFileFromResource(this.getClass(), "remote.yaml", ".tmp").getAbsolutePath(), "session")).toString(), startsWith("Configured "));
+        assertEquals("1", ((Iterator) acceptor.submit(Collections.singletonList("x = 1"))).next());
+        assertEquals("0", ((Iterator) acceptor.submit(Collections.singletonList("x - 1"))).next());
+        assertEquals("0", ((List<Result>) groovysh.getInterp().getContext().getProperty(DriverRemoteAcceptor.RESULT)).iterator().next().getString());
+    }
+
+    @Test
+    public void shouldConnectAndSubmitManagedSession() throws Exception {
+        assertThat(acceptor.connect(Arrays.asList(TestHelper.generateTempFileFromResource(this.getClass(), "remote.yaml", ".tmp").getAbsolutePath(), "session-managed")).toString(), startsWith("Configured "));
+        assertEquals("1", ((Iterator) acceptor.submit(Collections.singletonList("x = 1"))).next());
+        assertEquals("0", ((Iterator) acceptor.submit(Collections.singletonList("x - 1"))).next());
+        assertEquals("0", ((List<Result>) groovysh.getInterp().getContext().getProperty(DriverRemoteAcceptor.RESULT)).iterator().next().getString());
+    }
+
+    @Test
+    public void shouldConnectAndSubmitSimple() throws Exception {
+        assertThat(acceptor.connect(Collections.singletonList(TestHelper.generateTempFileFromResource(this.getClass(), "remote.yaml", ".tmp").getAbsolutePath())).toString(), startsWith("Configured "));
+        assertEquals("2", ((Iterator) acceptor.submit(Collections.singletonList("1+1"))).next());
+        assertEquals("2", ((List<Result>) groovysh.getInterp().getContext().getProperty(DriverRemoteAcceptor.RESULT)).iterator().next().getString());
+    }
+
+    @Test
+    public void shouldConnectAndSubmitSimpleList() throws Exception {
+        assertThat(acceptor.connect(Collections.singletonList(TestHelper.generateTempFileFromResource(this.getClass(), "remote.yaml", ".tmp").getAbsolutePath())).toString(), startsWith("Configured "));
+        assertThat(IteratorUtils.list(((Iterator<String>) acceptor.submit(Collections.singletonList("[1,2,3,4,5]")))), contains("1", "2", "3", "4", "5"));
+        assertThat(((List<Result>) groovysh.getInterp().getContext().getProperty(DriverRemoteAcceptor.RESULT)).stream().map(Result::getString).collect(Collectors.toList()), contains("1", "2", "3", "4", "5"));
+    }
+
+    @Test
+    public void shouldConnectAndReturnVertices() throws Exception {
+        assertThat(acceptor.connect(Collections.singletonList(TestHelper.generateTempFileFromResource(this.getClass(), "remote.yaml", ".tmp").getAbsolutePath())).toString(), startsWith("Configured "));
+        assertThat(IteratorUtils.list(((Iterator<String>) acceptor.submit(Collections.singletonList("g.addVertex('name','stephen');g.addVertex('name','marko');g.traversal().V()")))), hasSize(2));
+        assertThat(((List<Result>) groovysh.getInterp().getContext().getProperty(DriverRemoteAcceptor.RESULT)).stream().map(Result::getString).collect(Collectors.toList()), hasSize(2));
+    }
+
+    @Test
+    public void shouldConnectAndReturnVerticesWithAnAlias() throws Exception {
+        assertThat(acceptor.connect(Collections.singletonList(TestHelper.generateTempFileFromResource(this.getClass(), "remote.yaml", ".tmp").getAbsolutePath())).toString(), startsWith("Configured "));
+        acceptor.configure(Arrays.asList("alias", "x", "g"));
+        assertThat(IteratorUtils.list(((Iterator<String>) acceptor.submit(Collections.singletonList("x.addVertex('name','stephen');x.addVertex('name','marko');x.traversal().V()")))), hasSize(2));
+        assertThat(((List<Result>) groovysh.getInterp().getContext().getProperty(DriverRemoteAcceptor.RESULT)).stream().map(Result::getString).collect(Collectors.toList()), hasSize(2));
+    }
+
+    @Test
+    public void shouldConnectAndSubmitForNull() throws Exception {
+        assertThat(acceptor.connect(Collections.singletonList(TestHelper.generateTempFileFromResource(this.getClass(), "remote.yaml", ".tmp").getAbsolutePath())).toString(), startsWith("Configured "));
+        assertThat(IteratorUtils.list(((Iterator<String>) acceptor.submit(Collections.singletonList("g.traversal().V().drop().iterate();null")))), contains("null"));
+        assertThat(((List<Result>) groovysh.getInterp().getContext().getProperty(DriverRemoteAcceptor.RESULT)).stream().map(Result::getObject).collect(Collectors.toList()), contains("null"));
+    }
+
+    @Test
+    public void shouldConnectAndSubmitInSession() throws Exception {
+        assertThat(acceptor.connect(Arrays.asList(TestHelper.generateTempFileFromResource(this.getClass(), "remote.yaml", ".tmp").getAbsolutePath(), "session")).toString(), startsWith("Configured "));
+        assertEquals("2", ((Iterator) acceptor.submit(Collections.singletonList("x=1+1"))).next());
+        assertEquals("2", ((List<Result>) groovysh.getInterp().getContext().getProperty(DriverRemoteAcceptor.RESULT)).iterator().next().getString());
+        assertEquals("4", ((Iterator) acceptor.submit(Collections.singletonList("x+2"))).next());
+        assertEquals("4", ((List<Result>) groovysh.getInterp().getContext().getProperty(DriverRemoteAcceptor.RESULT)).iterator().next().getString());
+    }
+
+    @Test
+    public void shouldConnectAndSubmitInNamedSession() throws Exception {
+        assertThat(acceptor.connect(Arrays.asList(TestHelper.generateTempFileFromResource(this.getClass(), "remote.yaml", ".tmp").getAbsolutePath(), "session", "AAA")).toString(), startsWith("Configured "));
+        assertEquals("2", ((Iterator) acceptor.submit(Collections.singletonList("x=1+1"))).next());
+        assertEquals("2", ((List<Result>) groovysh.getInterp().getContext().getProperty(DriverRemoteAcceptor.RESULT)).iterator().next().getString());
+        assertEquals("4", ((Iterator) acceptor.submit(Collections.singletonList("x+2"))).next());
+        assertEquals("4", ((List<Result>) groovysh.getInterp().getContext().getProperty(DriverRemoteAcceptor.RESULT)).iterator().next().getString());
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorTest.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorTest.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorTest.java
new file mode 100644
index 0000000..01a7d73
--- /dev/null
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptorTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.console.jsr223;
+
+import org.apache.tinkerpop.gremlin.TestHelper;
+import org.apache.tinkerpop.gremlin.jsr223.console.RemoteException;
+import org.codehaus.groovy.tools.shell.Groovysh;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class DriverRemoteAcceptorTest {
+
+    private final Groovysh groovysh = new Groovysh();
+    private DriverRemoteAcceptor acceptor;
+
+    @Before
+    public void setUp() {
+        acceptor = new DriverRemoteAcceptor(new MockGroovyGremlinShellEnvironment(groovysh));
+    }
+
+    @After
+    public void tearDown() {
+        try {
+            acceptor.close();
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    @Test(expected = RemoteException.class)
+    public void shouldNotConfigureWithBadCommand() throws Exception {
+        acceptor.configure(Arrays.asList("test"));
+    }
+
+    @Test(expected = RemoteException.class)
+    public void shouldNotConfigureWithUnevenPairsOfAliases() throws Exception {
+        acceptor.configure(Arrays.asList("alias g social x"));
+    }
+
+    @Test
+    public void shouldResetAliases() throws Exception {
+        final Map<String,String> resetAliases = (Map<String,String>) acceptor.configure(Arrays.asList("alias", "g", "main.social"));
+        assertEquals(1, resetAliases.size());
+        assertEquals("main.social", resetAliases.get("g"));
+
+        assertEquals("Aliases cleared", acceptor.configure(Arrays.asList("alias", "reset")));
+
+        final Map<String,String> shownAliases = (Map<String,String>) acceptor.configure(Arrays.asList("alias", "show"));
+        assertEquals(0, shownAliases.size());
+    }
+
+    @Test
+    public void shouldAddOverwriteAndShowAliases() throws Exception {
+        final Map<String,String> aliases = (Map<String,String>) acceptor.configure(Arrays.asList("alias", "g", "social", "graph", "main"));
+        assertEquals(2, aliases.size());
+        assertEquals("social", aliases.get("g"));
+        assertEquals("main", aliases.get("graph"));
+
+        final Map<String,String> resetAliases = (Map<String,String>) acceptor.configure(Arrays.asList("alias", "g", "main.social"));
+        assertEquals(1, resetAliases.size());
+        assertEquals("main.social", resetAliases.get("g"));
+
+        final Map<String,String> shownAliases = (Map<String,String>) acceptor.configure(Arrays.asList("alias", "show"));
+        assertEquals(1, shownAliases.size());
+        assertEquals("main.social", shownAliases.get("g"));
+    }
+
+    @Test(expected = RemoteException.class)
+    public void shouldNotConnectWithEmptyArgs() throws Exception {
+        acceptor.connect(new ArrayList<>());
+    }
+
+    @Test(expected = RemoteException.class)
+    public void shouldNotConnectWithTooManyArgs() throws Exception {
+        acceptor.connect(Arrays.asList("two", "too", "many"));
+    }
+
+    @Test(expected = RemoteException.class)
+    public void shouldNotConnectWithInvalidConfigFile() throws Exception {
+        acceptor.connect(Arrays.asList("this-isnt-real.yaml"));
+    }
+
+    @Test
+    public void shouldConfigureTimeoutToMax() throws Exception {
+        acceptor.configure(Arrays.asList("timeout", "max"));
+        assertEquals(Integer.MAX_VALUE, acceptor.getTimeout());
+    }
+
+    @Test
+    public void shouldConfigureTimeoutToNone() throws Exception {
+        acceptor.configure(Arrays.asList("timeout", "none"));
+        assertEquals(DriverRemoteAcceptor.NO_TIMEOUT, acceptor.getTimeout());
+    }
+
+    @Test
+    public void shouldConfigureTimeout() throws Exception {
+        acceptor.configure(Arrays.asList("timeout", "123456"));
+        assertEquals(123456, acceptor.getTimeout());
+    }
+
+    @Test(expected = RemoteException.class)
+    public void shouldConfigureTimeoutNotLessThanNoTimeout() throws Exception {
+        acceptor.configure(Arrays.asList("timeout", "-1"));
+    }
+
+    @Test
+    public void shouldConnect() throws Exception {
+        // there is no gremlin server running for this test, but gremlin-driver lazily connects so this should
+        // be ok to just validate that a connection is created
+        assertThat(acceptor.connect(Arrays.asList(TestHelper.generateTempFileFromResource(this.getClass(), "remote.yaml", ".tmp").getAbsolutePath())).toString(), startsWith("Configured "));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptorIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptorIntegrateTest.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptorIntegrateTest.java
new file mode 100644
index 0000000..9a1c541
--- /dev/null
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptorIntegrateTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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.console.jsr223;
+
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import org.apache.commons.io.input.NullInputStream;
+import org.apache.tinkerpop.gremlin.console.GremlinGroovysh;
+import org.apache.tinkerpop.gremlin.console.Mediator;
+import org.apache.tinkerpop.gremlin.jsr223.console.RemoteException;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
+import org.codehaus.groovy.tools.shell.Groovysh;
+import org.codehaus.groovy.tools.shell.IO;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertThat;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GephiRemoteAcceptorIntegrateTest {
+    private static final Groovysh groovysh = new GremlinGroovysh(new Mediator(null));
+    private static int port = pickOpenPort();
+
+    private GephiRemoteAcceptor acceptor;
+
+    private final InputStream inputStream = new NullInputStream(0);
+    private final OutputStream outputStream = new ByteArrayOutputStream();
+    private final OutputStream errorStream = new ByteArrayOutputStream();
+    private final IO io = new IO(inputStream, outputStream, errorStream);
+
+    @Rule
+    public WireMockRule wireMockRule = new WireMockRule(port);
+
+    static {
+        final Graph graph = TinkerFactory.createModern();
+        groovysh.getInterp().getContext().setProperty("graph", graph);
+    }
+
+    @Before
+    public void before() throws Exception {
+        acceptor = new GephiRemoteAcceptor(new MockGroovyGremlinShellEnvironment(groovysh, io));
+        acceptor.configure(Arrays.asList("port", String.valueOf(port)));
+    }
+
+    @Test
+    public void shouldConnectWithDefaults() throws RemoteException {
+        assertThat(acceptor.connect(Collections.emptyList()).toString(), startsWith("Connection to Gephi - http://localhost:" + port + "/workspace1"));
+    }
+
+    @Test
+    public void shouldSubmitGraph() throws RemoteException {
+        stubFor(post(urlPathEqualTo("/workspace1"))
+                .withQueryParam("format", equalTo("JSON"))
+                .withQueryParam("operation", equalTo("updateGraph"))
+                .willReturn(aResponse()
+                        .withStatus(200)));
+
+        stubFor(get(urlPathEqualTo("/workspace1"))
+                .withQueryParam("operation", equalTo("getNode"))
+                .willReturn(aResponse()
+                        .withStatus(200)));
+
+        acceptor.submit(Arrays.asList("g = org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph.open();g.addVertex();g"));
+
+        wireMockRule.verify(4, postRequestedFor(urlPathEqualTo("/workspace1")));
+        wireMockRule.verify(1, getRequestedFor(urlPathEqualTo("/workspace1")));
+    }
+
+    @Test
+    public void shouldSubmitTraversalAfterConfigWithDefaultG() throws RemoteException {
+        stubFor(post(urlPathEqualTo("/workspace1"))
+                .withQueryParam("format", equalTo("JSON"))
+                .withQueryParam("operation", equalTo("updateGraph"))
+                .willReturn(aResponse()
+                        .withStatus(200)));
+
+        acceptor.configure(Arrays.asList("visualTraversal", "graph"));
+
+        // call iterate() as groovysh isn't rigged to auto-iterate
+        acceptor.submit(Arrays.asList(
+                "vg.V(2).in('knows').out('knows').has('age',org.apache.tinkerpop.gremlin.process.traversal.P.gt(30)).outE('created').has('weight',org.apache.tinkerpop.gremlin.process.traversal.P.gt(0.5d)).inV().iterate()"));
+
+        wireMockRule.verify(18, postRequestedFor(urlPathEqualTo("/workspace1")));
+    }
+
+    @Test
+    public void shouldSubmitTraversalAfterConfigWithDefinedG() throws RemoteException {
+        stubFor(post(urlPathEqualTo("/workspace1"))
+                .withQueryParam("format", equalTo("JSON"))
+                .withQueryParam("operation", equalTo("updateGraph"))
+                .willReturn(aResponse()
+                        .withStatus(200)));
+
+        acceptor.configure(Arrays.asList("visualTraversal", "graph", "x"));
+
+        // call iterate() as groovysh isn't rigged to auto-iterate
+        acceptor.submit(Arrays.asList(
+                "x.V(2).in('knows').out('knows').has('age',org.apache.tinkerpop.gremlin.process.traversal.P.gt(30)).outE('created').has('weight',org.apache.tinkerpop.gremlin.process.traversal.P.gt(0.5d)).inV().iterate()"));
+
+        wireMockRule.verify(18, postRequestedFor(urlPathEqualTo("/workspace1")));
+    }
+
+    @Test
+    public void shouldSubmitTraversalOverRepeat() throws RemoteException {
+        stubFor(post(urlPathEqualTo("/workspace1"))
+                .withQueryParam("format", equalTo("JSON"))
+                .withQueryParam("operation", equalTo("updateGraph"))
+                .willReturn(aResponse()
+                        .withStatus(200)));
+
+        acceptor.configure(Arrays.asList("visualTraversal", "graph"));
+
+        // call iterate() as groovysh isn't rigged to auto-iterate
+        acceptor.submit(Arrays.asList(
+                "vg.V(1).repeat(org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.__().out()).times(2).iterate()"));
+
+        wireMockRule.verify(13, postRequestedFor(urlPathEqualTo("/workspace1")));
+    }
+
+    @Test
+    public void shouldClearGraph() throws RemoteException {
+        stubFor(post(urlPathEqualTo("/workspace1"))
+                .withQueryParam("format", equalTo("JSON"))
+                .withQueryParam("operation", equalTo("updateGraph"))
+                .withRequestBody(equalToJson("{\"dn\":{\"filter\":\"ALL\"}}"))
+                .willReturn(aResponse()
+                        .withStatus(200)));
+
+        acceptor.submit(Arrays.asList("clear"));
+
+        wireMockRule.verify(1, postRequestedFor(urlPathEqualTo("/workspace1")));
+    }
+
+    private static int pickOpenPort() {
+        try (final ServerSocket socket = new ServerSocket(0)) {
+            return socket.getLocalPort();
+        } catch (IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/MockGroovyGremlinShellEnvironment.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/MockGroovyGremlinShellEnvironment.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/MockGroovyGremlinShellEnvironment.java
new file mode 100644
index 0000000..6184b54
--- /dev/null
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/MockGroovyGremlinShellEnvironment.java
@@ -0,0 +1,64 @@
+/*
+ * 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.console.jsr223;
+
+import org.apache.tinkerpop.gremlin.jsr223.console.GremlinShellEnvironment;
+import org.codehaus.groovy.tools.shell.Groovysh;
+import org.codehaus.groovy.tools.shell.IO;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class MockGroovyGremlinShellEnvironment implements GremlinShellEnvironment {
+
+    private final Groovysh groovysh;
+    private final IO io;
+
+    public MockGroovyGremlinShellEnvironment(final Groovysh groovysh) {
+        this(groovysh, null);
+    }
+
+    public MockGroovyGremlinShellEnvironment(final Groovysh groovysh, final IO io) {
+        this.groovysh = groovysh;
+        this.io = io;
+    }
+
+    @Override
+    public <T> T getVariable(final String variableName) {
+        return (T) groovysh.getInterp().getContext().getVariable(variableName);
+    }
+
+    @Override
+    public <T> void setVariable(final String variableName, final T variableValue) {
+        groovysh.getInterp().getContext().setVariable(variableName, variableValue);
+    }
+
+    @Override
+    public void println(final String line) {
+        if (null == io)
+            groovysh.getIo().out.println(line);
+        else
+            io.out.println(line);
+    }
+
+    @Override
+    public <T> T execute(final String line) {
+        return (T) groovysh.execute(line);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginTest.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginTest.java b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginTest.java
new file mode 100644
index 0000000..abecf8c
--- /dev/null
+++ b/gremlin-console/src/test/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.console.jsr223;
+
+import org.apache.commons.io.input.NullInputStream;
+import org.apache.tinkerpop.gremlin.console.plugin.ConsolePluginAcceptor;
+import org.apache.tinkerpop.gremlin.console.plugin.PluggedIn;
+import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory;
+import org.codehaus.groovy.tools.shell.Groovysh;
+import org.codehaus.groovy.tools.shell.IO;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class UtilitiesGremlinPluginTest {
+    private final InputStream inputStream = new NullInputStream(0);
+    private final OutputStream outputStream = new ByteArrayOutputStream();
+    private final OutputStream errorStream = new ByteArrayOutputStream();
+    private final IO io = new IO(inputStream, outputStream, errorStream);
+
+    @Test
+    public void shouldFailWithoutUtilitiesPlugin() throws Exception {
+        final Groovysh groovysh = new Groovysh();
+        try {
+            groovysh.execute("describeGraph(g.class)");
+            fail("Utilities were not loaded - this should fail.");
+        } catch (Exception ignored) {
+        }
+    }
+
+    @Test
+    public void shouldPluginUtilities() throws Exception {
+        final UtilitiesGremlinPlugin plugin = new UtilitiesGremlinPlugin();
+
+        final Groovysh groovysh = new Groovysh();
+        groovysh.getInterp().getContext().setProperty("g", TinkerFactory.createClassic());
+
+        final PluggedIn.GremlinPluginAdapter adapter = new PluggedIn.GremlinPluginAdapter(plugin, groovysh, io);
+        final ConsolePluginAcceptor acceptor = new ConsolePluginAcceptor(groovysh, io);
+
+        adapter.pluginTo(acceptor);
+
+        assertThat(groovysh.execute("describeGraph(org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph)").toString(), containsString("IMPLEMENTATION - org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/gremlin-server-integration.yaml
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/gremlin-server-integration.yaml b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/gremlin-server-integration.yaml
new file mode 100644
index 0000000..a7ef1a9
--- /dev/null
+++ b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/gremlin-server-integration.yaml
@@ -0,0 +1,54 @@
+# 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.
+
+host: localhost
+port: 45940
+threadPoolWorker: 1
+gremlinPool: 8
+scriptEvaluationTimeout: 30000
+serializedResponseTimeout: 30000
+graphs: {
+  g: conf/tinkergraph-empty.properties}
+plugins:
+  - tinkerpop.tinkergraph
+scriptEngines: {
+  gremlin-groovy: {
+    imports: [java.lang.Math],
+    staticImports: [java.lang.Math.PI]}}
+serializers:
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { custom: [groovy.json.JsonBuilder;org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer]}}
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { serializeResultToString: true}}
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0 }
+  - { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0 }
+processors:
+  - { className: org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor, config: { sessionTimeout: 28800000 }}
+metrics: {
+  consoleReporter: {enabled: true, interval: 180000},
+  csvReporter: {enabled: true, interval: 180000, fileName: /tmp/gremlin-server-metrics.csv},
+  jmxReporter: {enabled: true},
+  slf4jReporter: {enabled: true, interval: 180000},
+  gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST},
+  graphiteReporter: {enabled: false, interval: 180000}}
+threadPoolBoss: 1
+maxInitialLineLength: 4096
+maxHeaderSize: 8192
+maxChunkSize: 8192
+maxContentLength: 65536
+maxAccumulationBufferComponents: 1024
+resultIterationBatchSize: 64
+writeBufferHighWaterMark: 32768
+writeBufferHighWaterMark: 65536

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/remote.yaml
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/remote.yaml b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/remote.yaml
new file mode 100644
index 0000000..373934b
--- /dev/null
+++ b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/remote.yaml
@@ -0,0 +1,20 @@
+# 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.
+
+hosts: [localhost]
+port: 45940
+serializer: { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0, config: { serializeResultToString: true }}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/script-customizer-1.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/script-customizer-1.groovy b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/script-customizer-1.groovy
new file mode 100644
index 0000000..c2cc784
--- /dev/null
+++ b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/script-customizer-1.groovy
@@ -0,0 +1,3 @@
+x = 1 + 1
+y = 10 * x
+z = 1 + x + y
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/script-customizer-2.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/script-customizer-2.groovy b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/script-customizer-2.groovy
new file mode 100644
index 0000000..1a4f9a9
--- /dev/null
+++ b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/script-customizer-2.groovy
@@ -0,0 +1,2 @@
+l = g.V(z).out()
+        .group().by('name')
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/tinkergraph-empty.properties
----------------------------------------------------------------------
diff --git a/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/tinkergraph-empty.properties b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/tinkergraph-empty.properties
new file mode 100644
index 0000000..6590d39
--- /dev/null
+++ b/gremlin-console/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/tinkergraph-empty.properties
@@ -0,0 +1,18 @@
+# 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.
+
+gremlin.graph=org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/RemoteException.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/RemoteException.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/RemoteException.java
index f41d123..3eb5f69 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/RemoteException.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/RemoteException.java
@@ -24,7 +24,7 @@ package org.apache.tinkerpop.gremlin.groovy.plugin;
  * be displayed to the user in the Console.
  *
  * @author Stephen Mallette (http://stephen.genoprime.com)
- * @deprecated As of release 3.2.4, replaced by {@link org.apache.tinkerpop.gremlin.jsr223.RemoteException};
+ * @deprecated As of release 3.2.4, replaced by {@link org.apache.tinkerpop.gremlin.jsr223.console.RemoteException};
  */
 @Deprecated
 public class RemoteException extends Exception {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d62495b2/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 802593e..09aeede 100644
--- a/pom.xml
+++ b/pom.xml
@@ -295,6 +295,7 @@ limitations under the License.
                         <exclude>**/src/test/resources/META-INF/services/**</exclude>
                         <exclude>**/src/test/resources/org/apache/tinkerpop/gremlin/console/groovy/plugin/script-customizer-*.groovy</exclude>
                         <exclude>**/src/test/resources/org/apache/tinkerpop/gremlin/jsr223/script-customizer-*.groovy</exclude>
+                        <exclude>**/src/test/resources/org/apache/tinkerpop/gremlin/console/jsr223/script-customizer-*.groovy</exclude>
                         <exclude>**/src/main/resources/org/apache/tinkerpop/gremlin/structure/io/script/*.txt</exclude>
                         <exclude>**/src/main/ext/**</exclude>
                         <exclude>**/src/main/static/**</exclude>