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/02 11:32:35 UTC
[15/50] tinkerpop git commit: TINKERPOP-1562 Move RemoteAcceptor
related stuff to gremlin-core.
TINKERPOP-1562 Move RemoteAcceptor related stuff to gremlin-core.
Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/d7d6d5b2
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/d7d6d5b2
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/d7d6d5b2
Branch: refs/heads/TINKERPOP-1562
Commit: d7d6d5b2b8788fa420223d8986c27c535255494c
Parents: 8ee2225
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Mon Nov 21 13:13:30 2016 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Fri Dec 2 06:28:50 2016 -0500
----------------------------------------------------------------------
.../console/jsr223/GephiRemoteAcceptor.groovy | 372 +++++++++++++++++++
.../console/plugin/GephiRemoteAcceptor.groovy | 1 +
.../tinkerpop/gremlin/jsr223/GremlinModule.java | 9 +
.../gremlin/jsr223/ImportGremlinModule.java | 1 -
.../gremlin/jsr223/RemoteAcceptor.java | 81 ++++
.../gremlin/jsr223/RemoteException.java | 40 ++
.../gremlin/groovy/plugin/RemoteAcceptor.java | 2 +
.../gremlin/groovy/plugin/RemoteException.java | 2 +
8 files changed, 507 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d7d6d5b2/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..11e1e5c
--- /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.RemoteAcceptor
+import org.apache.tinkerpop.gremlin.jsr223.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/d7d6d5b2/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiRemoteAcceptor.groovy
----------------------------------------------------------------------
diff --git a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiRemoteAcceptor.groovy b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiRemoteAcceptor.groovy
index 4198444..30527a4 100644
--- a/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiRemoteAcceptor.groovy
+++ b/gremlin-console/src/main/groovy/org/apache/tinkerpop/gremlin/console/plugin/GephiRemoteAcceptor.groovy
@@ -40,6 +40,7 @@ import org.codehaus.groovy.tools.shell.IO
/**
* @author Stephen Mallette (http://stephen.genoprime.com)
* @author Randall Barnhart (randompi@gmail.com)
+ * @deprecated As of release 3.2.4, replaced by {@link org.apache.tinkerpop.gremlin.console.jsr223.GephiRemoteAcceptor}
*/
class GephiRemoteAcceptor implements RemoteAcceptor {
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d7d6d5b2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinModule.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinModule.java
index 20e9ff8..1077cf3 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/GremlinModule.java
@@ -58,4 +58,13 @@ public interface GremlinModule {
* @param scriptEngineName The name of the {@code ScriptEngine} or null to get all the available {@code Customizers}
*/
public Optional<Customizer[]> getCustomizers(final String scriptEngineName);
+
+ /**
+ * Allows a plugin to utilize features of the {@code :remote} and {@code :submit} commands of the Gremlin Console.
+ * This method does not need to be implemented if the plugin is not meant for the Console for some reason or
+ * if it does not intend to take advantage of those commands.
+ */
+ public default Optional<RemoteAcceptor> remoteAcceptor() {
+ return Optional.empty();
+ }
}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d7d6d5b2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/ImportGremlinModule.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/ImportGremlinModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/ImportGremlinModule.java
index 9fcbbce..e9ca477 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/ImportGremlinModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/ImportGremlinModule.java
@@ -23,7 +23,6 @@ import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
-import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d7d6d5b2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/RemoteAcceptor.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/RemoteAcceptor.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/RemoteAcceptor.java
new file mode 100644
index 0000000..f917c09
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/RemoteAcceptor.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.jsr223;
+
+import java.io.Closeable;
+import java.util.List;
+
+/**
+ * The Gremlin Console supports the {@code :remote} and {@code :submit} commands which provide standardized ways
+ * for plugins to provide "remote connections" to resources and a way to "submit" a command to those resources.
+ * A "remote connection" does not necessarily have to be a remote server. It simply refers to a resource that is
+ * external to the console.
+ * <p/>
+ * By implementing this interface and returning an instance of it through {@link GremlinModule#remoteAcceptor()} a
+ * plugin can hook into those commands and provide remoting features.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public interface RemoteAcceptor extends Closeable {
+
+ public static final String RESULT = "result";
+
+ /**
+ * Gets called when {@code :remote} is used in conjunction with the "connect" option. It is up to the
+ * implementation to decide how additional arguments on the line should be treated after "connect".
+ *
+ * @return an object to display as output to the user
+ * @throws RemoteException if there is a problem with connecting
+ */
+ public Object connect(final List<String> args) throws RemoteException;
+
+ /**
+ * Gets called when {@code :remote} is used in conjunction with the {@code config} option. It is up to the
+ * implementation to decide how additional arguments on the line should be treated after {@code config}.
+ *
+ * @return an object to display as output to the user
+ * @throws RemoteException if there is a problem with configuration
+ */
+ public Object configure(final List<String> args) throws RemoteException;
+
+ /**
+ * Gets called when {@code :submit} is executed. It is up to the implementation to decide how additional
+ * arguments on the line should be treated after {@code :submit}.
+ *
+ * @return an object to display as output to the user
+ * @throws RemoteException if there is a problem with submission
+ */
+ public Object submit(final List<String> args) throws RemoteException;
+
+ /**
+ * If the {@code RemoteAcceptor} is used in the Gremlin Console, then this method might be called to determine
+ * if it can be used in a fashion that supports the {@code :remote console} command. By default, this value is
+ * set to {@code false}.
+ * <p/>
+ * A {@code RemoteAcceptor} should only return {@code true} for this method if it expects that all activities it
+ * supports are executed through the {@code :sumbit} command. If the users interaction with the remote requires
+ * working with both local and remote evaluation at the same time, it is likely best to keep this method return
+ * {@code false}. A good example of this type of plugin would be the Gephi Plugin which uses {@code :remote config}
+ * to configure a local {@code TraversalSource} to be used and expects calls to {@code :submit} for the same body
+ * of analysis.
+ */
+ public default boolean allowRemoteConsole() {
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d7d6d5b2/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/RemoteException.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/RemoteException.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/RemoteException.java
new file mode 100644
index 0000000..a75e6d6
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/RemoteException.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.tinkerpop.gremlin.jsr223;
+
+/**
+ * A mapper {@code Exception} to be thrown when there are problems with processing a command given to a
+ * {@link RemoteAcceptor}. The message provided to the exception will
+ * be displayed to the user in the Console.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public class RemoteException extends Exception {
+ public RemoteException(final String message) {
+ super(message);
+ }
+
+ public RemoteException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+ public RemoteException(final Throwable cause) {
+ super(cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d7d6d5b2/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/RemoteAcceptor.java
----------------------------------------------------------------------
diff --git a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/RemoteAcceptor.java b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/RemoteAcceptor.java
index 0cf8bac..b3d03fe 100644
--- a/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/RemoteAcceptor.java
+++ b/gremlin-groovy/src/main/java/org/apache/tinkerpop/gremlin/groovy/plugin/RemoteAcceptor.java
@@ -33,7 +33,9 @@ import java.util.List;
* plugin can hook into those commands and provide remoting features.
*
* @author Stephen Mallette (http://stephen.genoprime.com)
+ * @deprecated As of release 3.2.4, replaced by {@link org.apache.tinkerpop.gremlin.jsr223.RemoteAcceptor};
*/
+@Deprecated
public interface RemoteAcceptor extends Closeable {
public static final String RESULT = "result";
http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/d7d6d5b2/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 62efda5..f41d123 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,9 @@ 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
public class RemoteException extends Exception {
public RemoteException(final String message) {
super(message);