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 2016/12/16 16:53:34 UTC
[20/50] tinkerpop git commit: TINKERPOP-1562 Added gremlin-console
plugins under the new model.
TINKERPOP-1562 Added gremlin-console plugins under the new model.
Had to rework the PluggedIn adapters a bit so that they could better handle Console environment variable.s
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/a91fb80e
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/a91fb80e
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/a91fb80e
Branch: refs/heads/TINKERPOP-1581
Commit: a91fb80e64ceb2e5c97b5f8c2ef20205d075ec18
Parents: bb5b47d
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Nov 22 16:35:16 2016 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Dec 2 06:28:51 2016 -0500
----------------------------------------------------------------------
.../tinkerpop/gremlin/console/Console.groovy | 4 +-
.../console/jsr223/GephiRemoteAcceptor.groovy | 372 +++++++++++++++++++
.../gremlin/console/plugin/PluggedIn.groovy | 14 +-
.../groovy/plugin/DriverGremlinPlugin.java | 2 +
.../groovy/plugin/DriverRemoteAcceptor.java | 2 +
.../groovy/plugin/GephiGremlinPlugin.java | 1 +
.../groovy/plugin/UtilitiesGremlinPlugin.java | 1 +
.../console/jsr223/DriverGremlinPlugin.java | 106 ++++++
.../console/jsr223/DriverRemoteAcceptor.java | 238 ++++++++++++
.../console/jsr223/GephiGremlinPlugin.java | 45 +++
.../console/jsr223/UtilitiesGremlinPlugin.java | 106 ++++++
...pache.tinkerpop.gremlin.jsr223.GremlinPlugin | 3 +
.../jsr223/UtilitiesGremlinPluginScript.groovy | 52 +++
.../groovy/plugin/GremlinPluginAdapterTest.java | 5 +-
14 files changed, 940 insertions(+), 11 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy
index cb6e90f..d39e085 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/Console.groovy
@@ -131,9 +131,9 @@ class Console {
def pluggedIn
if (Mediator.useV3d3) {
- pluggedIn = new PluggedIn(new PluggedIn.GremlinPluginAdapter(plugin), groovy, io, false)
+ pluggedIn = new PluggedIn(new PluggedIn.GremlinPluginAdapter((org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin) plugin, groovy, io), groovy, io, false)
} else {
- pluggedIn = new PluggedIn(plugin, groovy, io, false)
+ pluggedIn = new PluggedIn((GremlinPlugin) plugin, groovy, io, false)
}
mediator.availablePlugins.put(plugin.class.name, pluggedIn)
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/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
new file mode 100644
index 0000000..dbc1156
--- /dev/null
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/jsr223/GephiRemoteAcceptor.groovy
@@ -0,0 +1,372 @@
+/*
+ * 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.json.JsonOutput
+import groovy.json.JsonSlurper
+import groovy.transform.CompileStatic
+import org.apache.http.client.methods.CloseableHttpResponse
+import org.apache.http.client.methods.HttpUriRequest
+import org.apache.http.client.methods.RequestBuilder
+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.RemoteAcceptor
+import org.apache.tinkerpop.gremlin.jsr223.console.RemoteException
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource
+import org.apache.tinkerpop.gremlin.structure.Edge
+import org.apache.tinkerpop.gremlin.structure.Graph
+import org.apache.tinkerpop.gremlin.structure.Vertex
+import org.codehaus.groovy.tools.shell.Groovysh
+import org.codehaus.groovy.tools.shell.IO
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ * @author Randall Barnhart (randompi@gmail.com)
+ */
+class GephiRemoteAcceptor implements RemoteAcceptor {
+
+ private String host = "localhost"
+ private int port = 8080
+ private String workspace = "workspace1"
+
+ private final Groovysh shell
+ private final IO io
+
+ private final Random rand = new Random();
+ boolean traversalSubmittedForViz = false
+ long vizStepDelay
+ private float[] vizStartRGBColor
+ private float[] vizDefaultRGBColor
+ private char vizColorToFade
+ private float vizColorFadeRate
+ private float vizStartSize
+ private float vizSizeDecrementRate
+ private Map vertexAttributes = [:]
+
+ private CloseableHttpClient httpclient = HttpClients.createDefault();
+
+ public GephiRemoteAcceptor(final Groovysh shell, final IO io) {
+ this.shell = shell
+ this.io = io
+
+ // traversal visualization defaults
+ vizStepDelay = 1000; // 1 second pause between viz of steps
+ vizStartRGBColor = [0.0f, 1.0f, 0.5f] // light aqua green
+ vizDefaultRGBColor = [0.6f, 0.6f, 0.6f] // light grey
+ vizColorToFade = 'g' // will fade so blue is strongest
+ vizColorFadeRate = 0.7 // the multiplicative rate to fade visited vertices
+ vizStartSize = 10
+ vizSizeDecrementRate = 0.33f
+ }
+
+ @Override
+ connect(final List<String> args) throws RemoteException {
+ if (args.size() >= 1)
+ workspace = args[0]
+
+ if (args.size() >= 2)
+ host = args[1]
+
+ if (args.size() >= 3) {
+ try {
+ port = Integer.parseInt(args[2])
+ } catch (Exception ex) {
+ throw new RemoteException("Port must be an integer value")
+ }
+ }
+
+ def vizConfig = " with stepDelay:$vizStepDelay, startRGBColor:$vizStartRGBColor, " +
+ "colorToFade:$vizColorToFade, colorFadeRate:$vizColorFadeRate, startSize:$vizStartSize," +
+ "sizeDecrementRate:$vizSizeDecrementRate"
+
+ return "Connection to Gephi - http://$host:$port/$workspace" + vizConfig
+ }
+
+ @Override
+ Object configure(final List<String> args) throws RemoteException {
+ if (args.size() < 2)
+ throw new RemoteException("Invalid config arguments - check syntax")
+
+ if (args[0] == "host")
+ host = args[1]
+ else if (args[0] == "port") {
+ try {
+ port = Integer.parseInt(args[1])
+ } catch (Exception ignored) {
+ throw new RemoteException("Port must be an integer value")
+ }
+ } else if (args[0] == "workspace")
+ workspace = args[1]
+ else if (args[0] == "stepDelay")
+ parseVizStepDelay(args[1])
+ else if (args[0] == "startRGBColor")
+ parseVizStartRGBColor(args[1])
+ else if (args[0] == "colorToFade")
+ parseVizColorToFade(args[1])
+ else if (args[0] == "colorFadeRate")
+ parseVizColorFadeRate(args[1])
+ else if (args[0] == "sizeDecrementRate")
+ parseVizSizeDecrementRate(args[1])
+ else if (args[0] == "startSize")
+ parseVizStartSize(args[1])
+ else if (args[0] == "visualTraversal") {
+ def graphVar = shell.interp.context.getVariable(args[1])
+ if (!(graphVar instanceof Graph))
+ throw new RemoteException("Invalid argument to 'visualTraversal' - first parameter must be a Graph instance")
+
+ def gVar = args.size() == 3 ? args[2] : "vg"
+ def theG = GraphTraversalSource.build().with(new GephiTraversalVisualizationStrategy(this)).create(graphVar)
+ shell.interp.context.setVariable(gVar, theG)
+ } else
+ throw new RemoteException("Invalid config arguments - check syntax")
+
+ return "Connection to Gephi - http://$host:$port/$workspace" +
+ " with stepDelay:$vizStepDelay, startRGBColor:$vizStartRGBColor, " +
+ "colorToFade:$vizColorToFade, colorFadeRate:$vizColorFadeRate, startSize:$vizStartSize," +
+ "sizeDecrementRate:$vizSizeDecrementRate"
+ }
+
+ @Override
+ @CompileStatic
+ Object submit(final List<String> args) throws RemoteException {
+ final String line = String.join(" ", args)
+ if (line.trim() == "clear") {
+ clearGraph()
+ io.out.println("Gephi workspace cleared")
+ return
+ }
+
+ // need to clear the vertex attributes
+ vertexAttributes.clear()
+
+ // this tells the GraphTraversalVisualizationStrategy that if the line eval's to a traversal it should
+ // try to visualize it
+ traversalSubmittedForViz = true
+
+ // get the colors/sizes back to basics before trying visualize
+ resetColorsSizes()
+
+ final Object o = shell.execute(line)
+ if (o instanceof Graph) {
+ clearGraph()
+ def graph = (Graph) o
+ def g = graph.traversal()
+ g.V().sideEffect { addVertexToGephi(g, it.get()) }.iterate()
+ }
+
+ traversalSubmittedForViz = false
+ }
+
+ @Override
+ void close() throws IOException {
+ httpclient.close()
+ }
+
+ /**
+ * Visits the last set of vertices traversed and degrades their color and size.
+ */
+ def updateVisitedVertices(def List except = []) {
+ vertexAttributes.keySet().findAll{ vertexId -> !except.contains(vertexId) }.each { String vertexId ->
+ def attrs = vertexAttributes[vertexId]
+ float currentColor = attrs.color
+ currentColor *= vizColorFadeRate
+
+ int currentSize = attrs["size"]
+ currentSize = Math.max(vizStartSize, currentSize - (currentSize * vizSizeDecrementRate))
+
+ vertexAttributes.get(vertexId).color = currentColor
+ vertexAttributes.get(vertexId).size = currentSize
+
+ changeVertexAttributes(vertexId)
+ }
+ }
+
+ def changeVertexAttributes(def String vertexId) {
+ def props = [:]
+ props.put(vizColorToFade.toString(), vertexAttributes[vertexId].color)
+ props.put("size", vertexAttributes[vertexId].size)
+ updateGephiGraph([cn: [(vertexId): props]])
+ }
+
+ /**
+ * Visit a vertex traversed and initialize its color and size.
+ */
+ def visitVertexInGephi(def Vertex v) {
+ def props = [:]
+ props.put('r', vizStartRGBColor[0])
+ props.put('g', vizStartRGBColor[1])
+ props.put('b', vizStartRGBColor[2])
+ props.put('size', vizStartSize * 2.5)
+ props.put('visited', 1)
+
+ updateGephiGraph([cn: [(v.id().toString()): props]])
+
+ vertexAttributes[v.id().toString()] = [color: vizStartRGBColor[fadeColorIndex()], size: vizStartSize * 2.5, touch: 1]
+ }
+
+ def fadeColorIndex() {
+ if (vizColorToFade == 'r')
+ return 0
+ else if (vizColorToFade == 'g')
+ return 1
+ else if (vizColorToFade == 'b')
+ return 2
+ }
+
+ def addVertexToGephi(def GraphTraversalSource g, def Vertex v, def boolean ignoreEdges = false) {
+ // grab the first property value from the strategies of values
+ def props = g.V(v).valueMap().next().collectEntries { kv -> [(kv.key): kv.value[0]] }
+ props << [label: v.label()]
+ props.put('r', vizDefaultRGBColor[0])
+ props.put('g', vizDefaultRGBColor[1])
+ props.put('b', vizDefaultRGBColor[2])
+ props.put('x', rand.nextFloat())
+ props.put('y', rand.nextFloat())
+ props.put('size', 10)
+ props.put('visited', 0)
+
+ // only add if it does not exist in graph already
+ if (!getFromGephiGraph([operation: "getNode", id: v.id().toString()]).isPresent())
+ updateGephiGraph([an: [(v.id().toString()): props]])
+
+ if (!ignoreEdges) {
+ g.V(v).outE().sideEffect {
+ addEdgeToGephi(g, it.get())
+ }.iterate()
+ }
+ }
+
+ @CompileStatic
+ def addEdgeToGephi(def GraphTraversalSource g, def Edge e) {
+ def props = g.E(e).valueMap().next()
+ props.put('label', e.label())
+ props.put('source', e.outVertex().id().toString())
+ props.put('target', e.inVertex().id().toString())
+ props.put('directed', true)
+ props.put('visited', 0)
+
+ // make sure the in vertex is there but don't add its edges - that will happen later as we are looping
+ // all vertices in the graph
+ addVertexToGephi(g, e.inVertex(), true)
+
+ // both vertices are definitely there now, so add the edge
+ updateGephiGraph([ae: [(e.id().toString()): props]])
+ }
+
+ def clearGraph() {
+ updateGephiGraph([dn: [filter: "ALL"]])
+ }
+
+ def resetColorsSizes() {
+ updateGephiGraph([cn: [filter: [nodeAttribute: [attribute: "visited", value: 1]],
+ attributes: [size: 1, r: vizDefaultRGBColor[0], g: vizDefaultRGBColor[1], b: vizDefaultRGBColor[2]]]])
+ updateGephiGraph([ce: [filter: [edgeAttribute: [attribute: "visited", value: 1]],
+ attributes: [size: 1, r: vizDefaultRGBColor[0], g: vizDefaultRGBColor[1], b: vizDefaultRGBColor[2]]]])
+ }
+
+ def getFromGephiGraph(def Map queryArgs) {
+ def requestBuilder = RequestBuilder.get("http://$host:$port/$workspace")
+ queryArgs.each { requestBuilder = requestBuilder.addParameter(it.key, it.value) }
+
+ def httpResp = makeRequest(requestBuilder.build())
+ def resp = EntityUtils.toString(httpResp.entity)
+
+ // gephi streaming plugin does not set the content type or respect the Accept header - treat as text
+ if (resp.isEmpty())
+ return Optional.empty()
+ else
+ return Optional.of(new JsonSlurper().parseText(resp))
+ }
+
+ def updateGephiGraph(def Map postBody) {
+ def requestBuilder = RequestBuilder.post("http://$host:$port/$workspace")
+ .addParameter("format", "JSON")
+ .addParameter("operation", "updateGraph")
+ .setEntity(new StringEntity(JsonOutput.toJson(postBody)))
+ EntityUtils.consume(makeRequest(requestBuilder.build()).entity)
+ }
+
+ private CloseableHttpResponse makeRequest(HttpUriRequest request) {
+ def httpResp = httpclient.execute(request)
+ if (httpResp.getStatusLine().getStatusCode() == 200) {
+ return httpResp
+ } else {
+ def resp = EntityUtils.toString(httpResp.entity)
+ throw new RuntimeException("Unsuccessful request to Gephi - [${httpResp.getStatusLine().getStatusCode()}] ${httpResp.getStatusLine().getReasonPhrase()} - $resp")
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "Gephi - [$workspace]"
+ }
+
+ private void parseVizStepDelay(String arg) {
+ try {
+ vizStepDelay = Long.parseLong(arg)
+ } catch (Exception ignored) {
+ throw new RemoteException("The stepDelay must be a long value")
+ }
+ }
+
+ private void parseVizStartRGBColor(String arg) {
+ try {
+ vizStartRGBColor = arg[1..-2].tokenize(',')*.toFloat()
+ assert (vizStartRGBColor.length == 3)
+ } catch (Exception ignored) {
+ throw new RemoteException("The vizStartRGBColor must be an array of 3 float values, e.g. [0.0,1.0,0.5]")
+ }
+ }
+
+ private void parseVizColorToFade(String arg) {
+ try {
+ vizColorToFade = arg.charAt(0).toLowerCase();
+ assert (vizColorToFade == 'r' || vizColorToFade == 'g' || vizColorToFade == 'b')
+ } catch (Exception ignored) {
+ throw new RemoteException("The vizColorToFade must be one character value among: r, g, b, R, G, B")
+ }
+ }
+
+ private void parseVizColorFadeRate(String arg) {
+ try {
+ vizColorFadeRate = Float.parseFloat(arg)
+ } catch (Exception ignored) {
+ throw new RemoteException("The colorFadeRate must be a float value")
+ }
+ }
+
+ private void parseVizSizeDecrementRate(String arg) {
+ try {
+ vizSizeDecrementRate = Float.parseFloat(arg)
+ } catch (Exception ignored) {
+ throw new RemoteException("The sizeDecrementRate must be a float value")
+ }
+ }
+
+ private void parseVizStartSize(String arg) {
+ try {
+ vizStartSize = Float.parseFloat(arg)
+ } catch (Exception ignored) {
+ throw new RemoteException("The startSize must be a float value")
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/PluggedIn.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/PluggedIn.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/PluggedIn.groovy
index dc63a2f..7a08a9d 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/PluggedIn.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/PluggedIn.groovy
@@ -68,9 +68,13 @@ class PluggedIn {
public static class GremlinPluginAdapter implements GremlinPlugin {
org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin corePlugin
+ private final Groovysh shell
+ private final IO io
- public GremlinPluginAdapter(final org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin corePlugin) {
+ public GremlinPluginAdapter(final org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin corePlugin, final Groovysh shell, final IO io) {
this.corePlugin = corePlugin
+ this.shell = shell
+ this.io = io
}
@Override
@@ -103,11 +107,11 @@ class PluggedIn {
@Override
Optional<RemoteAcceptor> remoteAcceptor() {
// find a consoleCustomizer if available
- if (!corePlugin.getCustomizers("gremlin-groovy").any{ it instanceof ConsoleCustomizer })
- Optional.empty()
+ if (!corePlugin.getCustomizers("gremlin-groovy").isPresent() || !corePlugin.getCustomizers("gremlin-groovy").get().any{ it instanceof ConsoleCustomizer })
+ return Optional.empty()
- ConsoleCustomizer customizer = (ConsoleCustomizer) corePlugin.getCustomizers("gremlin-groovy").find{ it instanceof ConsoleCustomizer }
- return Optional.of(new RemoteAcceptorAdapter(customizer.remoteAcceptor))
+ ConsoleCustomizer customizer = (ConsoleCustomizer) corePlugin.getCustomizers("gremlin-groovy").get().find{ it instanceof ConsoleCustomizer }
+ return Optional.of(new RemoteAcceptorAdapter(customizer.getRemoteAcceptor([(ConsoleCustomizer.ENV_CONSOLE_SHELL): shell, (ConsoleCustomizer.ENV_CONSOLE_IO): io])))
}
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/DriverGremlinPlugin.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/DriverGremlinPlugin.java b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/DriverGremlinPlugin.java
index 2c52bd5..2f8fc75 100644
--- a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/DriverGremlinPlugin.java
+++ b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/DriverGremlinPlugin.java
@@ -35,7 +35,9 @@ import java.util.Set;
/**
* @author Stephen Mallette (http://stephen.genoprime.com)
+ * @deprecated As of release 3.2.4, replaced by {@link org.apache.tinkerpop.gremlin.console.jsr223.DriverGremlinPlugin}.
*/
+@Deprecated
public class DriverGremlinPlugin extends AbstractGremlinPlugin {
private static final Set<String> IMPORTS = new HashSet<String>() {{
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/DriverRemoteAcceptor.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/DriverRemoteAcceptor.java b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/DriverRemoteAcceptor.java
index c346540..80e8194 100644
--- a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/DriverRemoteAcceptor.java
+++ b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/DriverRemoteAcceptor.java
@@ -50,7 +50,9 @@ import java.util.stream.Stream;
*
* @author Stephen Mallette (http://stephen.genoprime.com)
* @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @deprecated As of release 3.2.4, replaced by {@link org.apache.tinkerpop.gremlin.console.jsr223.DriverRemoteAcceptor}.
*/
+@Deprecated
public class DriverRemoteAcceptor implements RemoteAcceptor {
public static final int NO_TIMEOUT = 0;
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GephiGremlinPlugin.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GephiGremlinPlugin.java b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GephiGremlinPlugin.java
index 6977aa8..df0541f 100644
--- a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GephiGremlinPlugin.java
+++ b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/GephiGremlinPlugin.java
@@ -29,6 +29,7 @@ import java.util.Optional;
/**
* @author Stephen Mallette (http://stephen.genoprime.com)
+ * @deprecated As of release 3.2.4, replaced by {@link org.apache.tinkerpop.gremlin.console.jsr223.GephiGremlinPlugin}.
*/
public class GephiGremlinPlugin extends AbstractGremlinPlugin {
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/UtilitiesGremlinPlugin.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/UtilitiesGremlinPlugin.java b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/UtilitiesGremlinPlugin.java
index 59c2b1a..d1c853d 100644
--- a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/UtilitiesGremlinPlugin.java
+++ b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/groovy/plugin/UtilitiesGremlinPlugin.java
@@ -34,6 +34,7 @@ import java.util.Set;
/**
* @author Stephen Mallette (http://stephen.genoprime.com)
+ * @deprecated As of release 3.2.4, replaced by {@link org.apache.tinkerpop.gremlin.console.jsr223.UtilitiesGremlinPlugin}.
*/
public class UtilitiesGremlinPlugin extends AbstractGremlinPlugin {
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java
new file mode 100644
index 0000000..89cec10
--- /dev/null
+++ b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverGremlinPlugin.java
@@ -0,0 +1,106 @@
+/*
+ * 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.driver.Client;
+import org.apache.tinkerpop.gremlin.driver.Cluster;
+import org.apache.tinkerpop.gremlin.driver.Host;
+import org.apache.tinkerpop.gremlin.driver.LoadBalancingStrategy;
+import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
+import org.apache.tinkerpop.gremlin.driver.Result;
+import org.apache.tinkerpop.gremlin.driver.ResultSet;
+import org.apache.tinkerpop.gremlin.driver.Tokens;
+import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
+import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
+import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseResult;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseStatus;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection;
+import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversal;
+import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteTraversalSideEffects;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV1d0;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerGremlinV2d0;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0;
+import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0;
+import org.apache.tinkerpop.gremlin.driver.ser.GryoLiteMessageSerializerV1d0;
+import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0;
+import org.apache.tinkerpop.gremlin.driver.ser.JsonBuilderGryoSerializer;
+import org.apache.tinkerpop.gremlin.driver.ser.MessageTextSerializer;
+import org.apache.tinkerpop.gremlin.driver.ser.SerTokens;
+import org.apache.tinkerpop.gremlin.driver.ser.SerializationException;
+import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
+import org.apache.tinkerpop.gremlin.jsr223.AbstractGremlinPlugin;
+import org.apache.tinkerpop.gremlin.jsr223.DefaultImportCustomizer;
+import org.apache.tinkerpop.gremlin.jsr223.ImportCustomizer;
+import org.apache.tinkerpop.gremlin.jsr223.console.ConsoleCustomizer;
+import org.codehaus.groovy.tools.shell.Groovysh;
+
+import java.util.Map;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class DriverGremlinPlugin extends AbstractGremlinPlugin {
+
+ private static final String NAME = "tinkerpop.server";
+
+ private static final ImportCustomizer imports = DefaultImportCustomizer.build()
+ .addClassImports(Cluster.class,
+ Client.class,
+ Host.class,
+ LoadBalancingStrategy.class,
+ MessageSerializer.class,
+ Result.class,
+ ResultSet.class,
+ Tokens.class,
+ ConnectionException.class,
+ ResponseException.class,
+ RequestMessage.class,
+ ResponseMessage.class,
+ ResponseResult.class,
+ ResponseStatus.class,
+ ResponseStatusCode.class,
+ GraphSONMessageSerializerGremlinV1d0.class,
+ GraphSONMessageSerializerGremlinV2d0.class,
+ GraphSONMessageSerializerV1d0.class,
+ GraphSONMessageSerializerV2d0.class,
+ GryoLiteMessageSerializerV1d0.class,
+ GryoMessageSerializerV1d0.class,
+ JsonBuilderGryoSerializer.class,
+ MessageTextSerializer.class,
+ SerializationException.class,
+ Serializers.class,
+ SerTokens.class,
+ DriverRemoteConnection.class,
+ DriverRemoteTraversal.class,
+ DriverRemoteTraversalSideEffects.class).create();
+
+ public DriverGremlinPlugin() {
+ super(NAME, imports, new DriverConsoleCustomizer());
+ }
+
+ private static class DriverConsoleCustomizer implements ConsoleCustomizer {
+ @Override
+ public org.apache.tinkerpop.gremlin.jsr223.console.RemoteAcceptor getRemoteAcceptor(final Map<String, Object> environment) {
+ return new DriverRemoteAcceptor((Groovysh) environment.get(ConsoleCustomizer.ENV_CONSOLE_SHELL));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptor.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptor.java b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptor.java
new file mode 100644
index 0000000..93ac184
--- /dev/null
+++ b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/DriverRemoteAcceptor.java
@@ -0,0 +1,238 @@
+/*
+ * 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.lang.exception.ExceptionUtils;
+import org.apache.tinkerpop.gremlin.driver.Client;
+import org.apache.tinkerpop.gremlin.driver.Cluster;
+import org.apache.tinkerpop.gremlin.driver.Result;
+import org.apache.tinkerpop.gremlin.driver.ResultSet;
+import org.apache.tinkerpop.gremlin.driver.exception.ResponseException;
+import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
+import org.apache.tinkerpop.gremlin.jsr223.console.RemoteAcceptor;
+import org.apache.tinkerpop.gremlin.jsr223.console.RemoteException;
+import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
+import org.codehaus.groovy.tools.shell.Groovysh;
+
+import javax.security.sasl.SaslException;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.stream.Stream;
+
+/**
+ * A {@link RemoteAcceptor} that takes input from the console and sends it to Gremlin Server over the standard
+ * Java driver.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public class DriverRemoteAcceptor implements RemoteAcceptor {
+ public static final int NO_TIMEOUT = 0;
+
+ private Cluster currentCluster;
+ private Client currentClient;
+ private int timeout = NO_TIMEOUT;
+ private Map<String,String> aliases = new HashMap<>();
+ private Optional<String> session = Optional.empty();
+
+ private static final String TOKEN_RESET = "reset";
+ private static final String TOKEN_SHOW = "show";
+
+ /**
+ * @deprecated As of 3.1.3, replaced by "none" option
+ */
+ @Deprecated
+ private static final String TOKEN_MAX = "max";
+ private static final String TOKEN_NONE = "none";
+ private static final String TOKEN_TIMEOUT = "timeout";
+ private static final String TOKEN_ALIAS = "alias";
+ private static final String TOKEN_SESSION = "session";
+ private static final String TOKEN_SESSION_MANAGED = "session-managed";
+ private static final List<String> POSSIBLE_TOKENS = Arrays.asList(TOKEN_TIMEOUT, TOKEN_ALIAS);
+
+ private final Groovysh shell;
+
+ public DriverRemoteAcceptor(final Groovysh shell) {
+ this.shell = shell;
+ }
+
+ @Override
+ public Object connect(final List<String> args) throws RemoteException {
+ if (args.size() < 1) throw new RemoteException("Expects the location of a configuration file as an argument");
+
+ try {
+ this.currentCluster = Cluster.open(args.get(0));
+ final boolean useSession = args.size() >= 2 && (args.get(1).equals(TOKEN_SESSION) || args.get(1).equals(TOKEN_SESSION_MANAGED));
+ if (useSession) {
+ final String sessionName = args.size() == 3 ? args.get(2) : UUID.randomUUID().toString();
+ session = Optional.of(sessionName);
+
+ final boolean managed = args.get(1).equals(TOKEN_SESSION_MANAGED);
+
+ this.currentClient = this.currentCluster.connect(sessionName, managed);
+ } else {
+ this.currentClient = this.currentCluster.connect();
+ }
+ this.currentClient.init();
+ return String.format("Configured %s", this.currentCluster) + getSessionStringSegment();
+ } catch (final FileNotFoundException ignored) {
+ throw new RemoteException("The 'connect' option must be accompanied by a valid configuration file");
+ } catch (final Exception ex) {
+ throw new RemoteException("Error during 'connect' - " + ex.getMessage(), ex);
+ }
+ }
+
+ @Override
+ public Object configure(final List<String> args) throws RemoteException {
+ final String option = args.size() == 0 ? "" : args.get(0);
+ if (!POSSIBLE_TOKENS.contains(option))
+ throw new RemoteException(String.format("The 'config' option expects one of ['%s'] as an argument", String.join(",", POSSIBLE_TOKENS)));
+
+ final List<String> arguments = args.subList(1, args.size());
+
+ if (option.equals(TOKEN_TIMEOUT)) {
+ final String errorMessage = "The timeout option expects a positive integer representing milliseconds or 'none' as an argument";
+ if (arguments.size() != 1) throw new RemoteException(errorMessage);
+ try {
+ // first check for MAX timeout then NONE and finally parse the config to int. "max" is now "deprecated"
+ // in the sense that it will no longer be promoted. support for it will be removed at a later date
+ timeout = arguments.get(0).equals(TOKEN_MAX) ? Integer.MAX_VALUE :
+ arguments.get(0).equals(TOKEN_NONE) ? NO_TIMEOUT : Integer.parseInt(arguments.get(0));
+ if (timeout < NO_TIMEOUT) throw new RemoteException("The value for the timeout cannot be less than " + NO_TIMEOUT);
+ return timeout == NO_TIMEOUT ? "Remote timeout is disabled" : "Set remote timeout to " + timeout + "ms";
+ } catch (Exception ignored) {
+ throw new RemoteException(errorMessage);
+ }
+ } else if (option.equals(TOKEN_ALIAS)) {
+ if (arguments.size() == 1 && arguments.get(0).equals(TOKEN_RESET)) {
+ aliases.clear();
+ return "Aliases cleared";
+ }
+
+ if (arguments.size() == 1 && arguments.get(0).equals(TOKEN_SHOW)) {
+ return aliases;
+ }
+
+ if (arguments.size() % 2 != 0)
+ throw new RemoteException("Arguments to alias must be 'reset' to clear any existing alias settings or key/value alias/binding pairs");
+
+ final Map<String,Object> aliasMap = ElementHelper.asMap(arguments.toArray());
+ aliases.clear();
+ aliasMap.forEach((k,v) -> aliases.put(k, v.toString()));
+ return aliases;
+ }
+
+ return this.toString();
+ }
+
+ @Override
+ public Object submit(final List<String> args) throws RemoteException {
+ final String line = getScript(String.join(" ", args), this.shell);
+
+ try {
+ final List<Result> resultSet = send(line);
+ this.shell.getInterp().getContext().setProperty(RESULT, resultSet);
+ return resultSet.stream().map(result -> result.getObject()).iterator();
+ } catch (SaslException sasl) {
+ throw new RemoteException("Security error - check username/password and related settings", sasl);
+ } catch (Exception ex) {
+ final Optional<ResponseException> inner = findResponseException(ex);
+ if (inner.isPresent()) {
+ final ResponseException responseException = inner.get();
+ if (responseException.getResponseStatusCode() == ResponseStatusCode.SERVER_ERROR_SERIALIZATION)
+ throw new RemoteException(String.format("Server could not serialize the result requested. Server error - %s. Note that the class must be serializable by the client and server for proper operation.", responseException.getMessage()));
+ else
+ throw new RemoteException(responseException.getMessage());
+ } else if (ex.getCause() != null) {
+ final Throwable rootCause = ExceptionUtils.getRootCause(ex);
+ if (rootCause instanceof TimeoutException)
+ throw new RemoteException("Host did not respond in a timely fashion - check the server status and submit again.");
+ else
+ throw new RemoteException(rootCause.getMessage());
+ } else
+ throw new RemoteException(ex.getMessage());
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (this.currentClient != null) this.currentClient.close();
+ if (this.currentCluster != null) this.currentCluster.close();
+ }
+
+ public int getTimeout() {
+ return timeout;
+ }
+
+ private List<Result> send(final String gremlin) throws SaslException {
+ try {
+ final ResultSet rs = this.currentClient.submitAsync(gremlin, aliases, Collections.emptyMap()).get();
+ return timeout > NO_TIMEOUT ? rs.all().get(timeout, TimeUnit.MILLISECONDS) : rs.all().get();
+ } catch(TimeoutException ignored) {
+ throw new IllegalStateException("Request timed out while processing - increase the timeout with the :remote command");
+ } catch (Exception e) {
+ // handle security error as-is and unwrapped
+ final Optional<Throwable> throwable = Stream.of(ExceptionUtils.getThrowables(e)).filter(t -> t instanceof SaslException).findFirst();
+ if (throwable.isPresent())
+ throw (SaslException) throwable.get();
+
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean allowRemoteConsole() {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Gremlin Server - [" + this.currentCluster + "]" + getSessionStringSegment();
+ }
+
+ private Optional<ResponseException> findResponseException(final Throwable ex) {
+ if (ex instanceof ResponseException)
+ return Optional.of((ResponseException) ex);
+
+ if (null == ex.getCause())
+ return Optional.empty();
+
+ return findResponseException(ex.getCause());
+ }
+
+ private String getSessionStringSegment() {
+ return session.isPresent() ? String.format("-[%s]", session.get()) : "";
+ }
+
+ /**
+ * Retrieve a script as defined in the shell context. This allows for multi-line scripts to be submitted.
+ */
+ public static String getScript(final String submittedScript, final Groovysh shell) {
+ return submittedScript.startsWith("@") ? shell.getInterp().getContext().getProperty(submittedScript.substring(1)).toString() : submittedScript;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiGremlinPlugin.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiGremlinPlugin.java b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiGremlinPlugin.java
new file mode 100644
index 0000000..7698112
--- /dev/null
+++ b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/GephiGremlinPlugin.java
@@ -0,0 +1,45 @@
+/*
+ * 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.AbstractGremlinPlugin;
+import org.apache.tinkerpop.gremlin.jsr223.console.ConsoleCustomizer;
+import org.codehaus.groovy.tools.shell.Groovysh;
+import org.codehaus.groovy.tools.shell.IO;
+
+import java.util.Map;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class GephiGremlinPlugin extends AbstractGremlinPlugin {
+ private static final String NAME = "tinkerpop.gephi";
+
+ public GephiGremlinPlugin() {
+ super(NAME, new GephiConsoleCustomizer());
+ }
+
+ private static class GephiConsoleCustomizer implements ConsoleCustomizer {
+ @Override
+ public org.apache.tinkerpop.gremlin.jsr223.console.RemoteAcceptor getRemoteAcceptor(final Map<String, Object> environment) {
+ return new GephiRemoteAcceptor((Groovysh) environment.get(ConsoleCustomizer.ENV_CONSOLE_SHELL),
+ (IO) environment.get(ConsoleCustomizer.ENV_CONSOLE_IO));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPlugin.java
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPlugin.java b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPlugin.java
new file mode 100644
index 0000000..57bacda
--- /dev/null
+++ b/gremlin-console/src/main/java/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPlugin.java
@@ -0,0 +1,106 @@
+/*
+ * 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 groovyx.gbench.Benchmark;
+import groovyx.gbench.BenchmarkStaticExtension;
+import groovyx.gprof.ProfileStaticExtension;
+import groovyx.gprof.Profiler;
+import org.apache.tinkerpop.gremlin.jsr223.AbstractGremlinPlugin;
+import org.apache.tinkerpop.gremlin.jsr223.DefaultImportCustomizer;
+import org.apache.tinkerpop.gremlin.jsr223.DefaultScriptCustomizer;
+import org.apache.tinkerpop.gremlin.jsr223.ImportCustomizer;
+import org.apache.tinkerpop.gremlin.jsr223.ScriptCustomizer;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+/**
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class UtilitiesGremlinPlugin extends AbstractGremlinPlugin {
+
+ private static final String NAME = "tinkerpop.utilities";
+
+ private static final ImportCustomizer imports;
+
+ private static final ScriptCustomizer scripts;
+
+ static {
+ try {
+ imports = DefaultImportCustomizer.build()
+ .addClassImports(groovyx.gbench.Benchmark.class,
+ groovyx.gbench.BenchmarkBuilder.class,
+ groovyx.gbench.BenchmarkConstants.class,
+ groovyx.gbench.BenchmarkContext.class,
+ groovyx.gbench.Benchmarker.class,
+ groovyx.gbench.BenchmarkList.class,
+ groovyx.gbench.BenchmarkLogger.class,
+ groovyx.gbench.BenchmarkMath.class,
+ groovyx.gbench.BenchmarkMeasure.class,
+ groovyx.gbench.BenchmarkStaticExtension.class,
+ groovyx.gbench.BenchmarkSystem.class,
+ groovyx.gbench.BenchmarkTime.class,
+ groovyx.gbench.BenchmarkWarmUp.class,
+ groovyx.gprof.Profiler.class,
+ groovyx.gprof.ProfileStaticExtension.class,
+ groovyx.gprof.CallFilter.class,
+ groovyx.gprof.CallInfo.class,
+ groovyx.gprof.CallInterceptor.class,
+ groovyx.gprof.CallMatcher.class,
+ groovyx.gprof.CallTree.class,
+ groovyx.gprof.MethodCallFilter.class,
+ groovyx.gprof.MethodCallInfo.class,
+ groovyx.gprof.MethodInfo.class,
+ groovyx.gprof.ProfileMetaClass.class,
+ groovyx.gprof.ProxyReport.class,
+ groovyx.gprof.Report.class,
+ groovyx.gprof.ReportElement.class,
+ groovyx.gprof.ReportNormalizer.class,
+ groovyx.gprof.ReportPrinter.class,
+ groovyx.gprof.ThreadInfo.class,
+ groovyx.gprof.ThreadRunFilter.class,
+ groovyx.gprof.Utils.class)
+ .addMethodImports(
+ ProfileStaticExtension.class.getMethod("profile", Object.class, Callable.class),
+ ProfileStaticExtension.class.getMethod("profile", Object.class, Map.class, Callable.class)).create();
+
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(UtilitiesGremlinPlugin.class.getResourceAsStream("UtilitiesGremlinPluginScript.groovy")));
+ final List<String> lines = new ArrayList<>();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ lines.add(line);
+ }
+ reader.close();
+
+ scripts = new DefaultScriptCustomizer(Collections.singletonList(lines));
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public UtilitiesGremlinPlugin() {
+ super(NAME, imports, scripts);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin b/gremlin-console/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin
new file mode 100644
index 0000000..631c889
--- /dev/null
+++ b/gremlin-console/src/main/resources/META-INF/services/org.apache.tinkerpop.gremlin.jsr223.GremlinPlugin
@@ -0,0 +1,3 @@
+org.apache.tinkerpop.gremlin.console.jsr223.DriverGremlinPlugin
+org.apache.tinkerpop.gremlin.console.jsr223.GephiGremlinPlugin
+org.apache.tinkerpop.gremlin.console.jsr223.UtilitiesGremlinPlugin
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginScript.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginScript.groovy b/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginScript.groovy
new file mode 100644
index 0000000..5f5e3c6
--- /dev/null
+++ b/gremlin-console/src/main/resources/org/apache/tinkerpop/gremlin/console/jsr223/UtilitiesGremlinPluginScript.groovy
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+/**
+ * @author Daniel Kuppitz (http://thinkaurelius.com)
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+
+describeGraph = { Class<? extends org.apache.tinkerpop.gremlin.structure.Graph> c ->
+ def lf = System.getProperty("line.separator")
+ def optIns = c.getAnnotationsByType(org.apache.tinkerpop.gremlin.structure.Graph.OptIn)
+ def optOuts = c.getAnnotationsByType(org.apache.tinkerpop.gremlin.structure.Graph.OptOut)
+
+ def optInCount = optIns != null ? optIns.size() : 0
+ def optOutCount = optOuts != null ? optOuts.size() : 0
+ def suitesSupported = optIns != null && optIns.size() > 0 ? optIns.collect { "> " + it.value() }.join(lf) : "> none"
+ def testsOptedOut = optOuts != null && optOuts.size() > 0 ? optOuts.collect { "> " + it.test() + "#" + it.method() + "${lf}\t\"" + it.reason() + "\"" }.join(lf) : "> none";
+
+ // not the use of {lf} here rather than triple quoted string is that groovy 2.4.0 seems to have trouble
+ // parsing that into groovysh - note the bug report here: https://jira.codehaus.org/browse/GROOVY-7290
+ return "${lf}" +
+"IMPLEMENTATION - ${c.getCanonicalName()} ${lf}" +
+"TINKERPOP TEST SUITE ${lf}" +
+"- Compliant with ($optInCount of 10 suites) ${lf}" +
+"$suitesSupported ${lf}" +
+"- Opts out of $optOutCount individual tests ${lf}" +
+"$testsOptedOut ${lf}" +
+"- NOTE - ${lf}" +
+"The describeGraph() function shows information about a Graph implementation. ${lf}" +
+"It uses information found in Java Annotations on the implementation itself to ${lf}" +
+"determine this output and does not assess the actual code of the test cases of ${lf}" +
+"the implementation itself. Compliant implementations will faithfully and ${lf}" +
+"honestly supply these Annotations to provide the most accurate depiction of ${lf}" +
+"their support."
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/a91fb80e/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 77422da..dd582b1 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
@@ -19,10 +19,7 @@
package org.apache.tinkerpop.gremlin.console.groovy.plugin;
import org.apache.tinkerpop.gremlin.console.plugin.PluggedIn;
-import org.apache.tinkerpop.gremlin.jsr223.BindingsCustomizer;
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;
import java.time.DayOfWeek;
@@ -44,7 +41,7 @@ public class GremlinPluginAdapterTest {
.classImports(java.awt.Color.class, java.sql.CallableStatement.class)
.enumImports(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY)
.methodImports(DayOfWeek.class.getMethod("from", TemporalAccessor.class), DayOfWeek.class.getMethod("values")).create();
- final PluggedIn.GremlinPluginAdapter adapter = new PluggedIn.GremlinPluginAdapter(plugin);
+ final PluggedIn.GremlinPluginAdapter adapter = new PluggedIn.GremlinPluginAdapter(plugin, null, null);
assertEquals(plugin.getName(), adapter.getName());