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/04/20 22:14:07 UTC

[1/6] incubator-tinkerpop git commit: Fixed minor grammatical error in dev release docs. [Forced Update!]

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1269 38b474a7c -> 75e875700 (forced update)


Fixed minor grammatical error in dev release docs.


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

Branch: refs/heads/TINKERPOP-1269
Commit: 3a4e2af22dc015c090c85d6efa0c7601a764d605
Parents: da31876
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Apr 20 08:25:38 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Apr 20 08:25:38 2016 -0400

----------------------------------------------------------------------
 docs/src/dev/developer/release.asciidoc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/3a4e2af2/docs/src/dev/developer/release.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/dev/developer/release.asciidoc b/docs/src/dev/developer/release.asciidoc
index 461919b..36f7434 100644
--- a/docs/src/dev/developer/release.asciidoc
+++ b/docs/src/dev/developer/release.asciidoc
@@ -157,7 +157,7 @@ Release & Promote
 . `cd release; svn add xx.yy.zz/; svn ci -m "TinkerPop xx.yy.zz release"`
 . Update homepage with references to latest distribution and to other internal links elsewhere on the page.
 . Wait for Apache Central to sync the jars and src (link:http://repo1.maven.org/maven2/org/apache/tinkerpop/tinkerpop/[http://repo1.maven.org/maven2/org/apache/tinkerpop/tinkerpop/]).
-. If there is are releases present in SVN that represents lines of code that are no longer under development, then remove those releases. In other words, if `3.1.0-incubating` is present and `3.1.1-incubating` is released then remove `3.1.0-incubating`.  However, if `3.0.2-incubating` is present and that line of code is still under potential development, it may stay.
+. If there are releases present in SVN that represents lines of code that are no longer under development, then remove those releases. In other words, if `3.1.0-incubating` is present and `3.1.1-incubating` is released then remove `3.1.0-incubating`.  However, if `3.0.2-incubating` is present and that line of code is still under potential development, it may stay.
 . Announce release on `dev@`/`gremlin-users@` mailing lists and tweet from `@apachetinkerpop`
 
 Email Templates


[5/6] incubator-tinkerpop git commit: Added ability to pass an SslContext to the driver.

Posted by sp...@apache.org.
Added ability to pass an SslContext to the driver.

This will be useful if the user needs more complex ssl configuration than the Cluster builder allows.


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

Branch: refs/heads/TINKERPOP-1269
Commit: 9996066189686812befdeb69e33ef2e9a8a6b9b7
Parents: cfa95c8
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Apr 20 13:50:01 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Apr 20 15:07:15 2016 -0400

----------------------------------------------------------------------
 .../tinkerpop/gremlin/driver/Channelizer.java   |  29 +----
 .../tinkerpop/gremlin/driver/Cluster.java       | 121 +++++++++++++------
 .../server/GremlinServerIntegrateTest.java      |  23 ++++
 .../GremlinServerSessionIntegrateTest.java      |   1 +
 4 files changed, 107 insertions(+), 67 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/99960661/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
index c850a11..40be11c 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
@@ -23,7 +23,6 @@ import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
 import io.netty.handler.ssl.SslContextBuilder;
 import io.netty.handler.ssl.SslProvider;
 import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
-import io.netty.handler.ssl.util.SelfSignedCertificate;
 import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
 import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinRequestEncoder;
 import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinResponseDecoder;
@@ -43,9 +42,7 @@ import io.netty.handler.ssl.SslContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.net.ssl.SSLException;
 import java.io.File;
-import java.security.cert.CertificateException;
 import java.util.Optional;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentMap;
@@ -120,7 +117,7 @@ public interface Channelizer extends ChannelHandler {
             final Optional<SslContext> sslCtx;
             if (supportsSsl()) {
                 try {
-                    sslCtx = Optional.of(createSSLContext(cluster.connectionPoolSettings()));
+                    sslCtx = Optional.of(cluster.createSSLContext());
                 } catch (Exception ex) {
                     throw new RuntimeException(ex);
                 }
@@ -136,30 +133,6 @@ public interface Channelizer extends ChannelHandler {
             pipeline.addLast(PIPELINE_GREMLIN_SASL_HANDLER, new Handler.GremlinSaslAuthenticationHandler(cluster.authProperties()));
             pipeline.addLast(PIPELINE_GREMLIN_HANDLER, new Handler.GremlinResponseHandler(pending));
         }
-
-        private SslContext createSSLContext(final Settings.ConnectionPoolSettings sslSettings) throws Exception  {
-            final SslProvider provider = SslProvider.JDK;
-
-            final SslContextBuilder builder = SslContextBuilder.forClient();
-            if (cluster.connectionPoolSettings().trustCertChainFile != null)
-                builder.trustManager(new File(cluster.connectionPoolSettings().trustCertChainFile));
-            else {
-                logger.warn("SSL configured without a trustCertChainFile and thus trusts all certificates without verification (not suitable for production)");
-                builder.trustManager(InsecureTrustManagerFactory.INSTANCE);
-            }
-
-            if (null != sslSettings.keyCertChainFile && null != sslSettings.keyFile) {
-                final File keyCertChainFile = new File(sslSettings.keyCertChainFile);
-                final File keyFile = new File(sslSettings.keyFile);
-
-                // note that keyPassword may be null here if the keyFile is not password-protected.
-                builder.keyManager(keyCertChainFile, keyFile, sslSettings.keyPassword);
-            }
-
-            builder.sslProvider(provider);
-
-            return builder.build();
-        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/99960661/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
index 7ae898b..3fa11f7 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
@@ -20,11 +20,17 @@ package org.apache.tinkerpop.gremlin.driver;
 
 import io.netty.buffer.PooledByteBufAllocator;
 import io.netty.channel.ChannelOption;
+import io.netty.handler.ssl.SslContext;
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.SslProvider;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
 import org.apache.tinkerpop.gremlin.driver.ser.Serializers;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.net.ssl.TrustManager;
 import java.io.File;
@@ -38,6 +44,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -52,15 +59,12 @@ import java.util.stream.Collectors;
  * @author Stephen Mallette (http://stephen.genoprime.com)
  */
 public final class Cluster {
+    private static final Logger logger = LoggerFactory.getLogger(Cluster.class);
 
     private Manager manager;
 
-    private Cluster(final List<InetSocketAddress> contactPoints, final MessageSerializer serializer,
-                    final int nioPoolSize, final int workerPoolSize,
-                    final Settings.ConnectionPoolSettings connectionPoolSettings,
-                    final LoadBalancingStrategy loadBalancingStrategy,
-                    final AuthProperties authProps) {
-        this.manager = new Manager(contactPoints, serializer, nioPoolSize, workerPoolSize, connectionPoolSettings, loadBalancingStrategy, authProps);
+    private Cluster(final Builder builder) {
+        this.manager = new Manager(builder);
     }
 
     public synchronized void init() {
@@ -268,6 +272,34 @@ public final class Cluster {
         return manager.allHosts();
     }
 
+    SslContext createSSLContext() throws Exception  {
+        // if the context is provided then just use that and ignore the other settings
+        if (manager.sslContextOptional.isPresent()) return manager.sslContextOptional.get();
+
+        final SslProvider provider = SslProvider.JDK;
+        final Settings.ConnectionPoolSettings connectionPoolSettings = connectionPoolSettings();
+        final SslContextBuilder builder = SslContextBuilder.forClient();
+
+        if (connectionPoolSettings.trustCertChainFile != null)
+            builder.trustManager(new File(connectionPoolSettings.trustCertChainFile));
+        else {
+            logger.warn("SSL configured without a trustCertChainFile and thus trusts all certificates without verification (not suitable for production)");
+            builder.trustManager(InsecureTrustManagerFactory.INSTANCE);
+        }
+
+        if (null != connectionPoolSettings.keyCertChainFile && null != connectionPoolSettings.keyFile) {
+            final File keyCertChainFile = new File(connectionPoolSettings.keyCertChainFile);
+            final File keyFile = new File(connectionPoolSettings.keyFile);
+
+            // note that keyPassword may be null here if the keyFile is not password-protected.
+            builder.keyManager(keyCertChainFile, keyFile, connectionPoolSettings.keyPassword);
+        }
+
+        builder.sslProvider(provider);
+
+        return builder.build();
+    }
+
     public final static class Builder {
         private List<InetAddress> addresses = new ArrayList<>();
         private int port = 8182;
@@ -292,6 +324,7 @@ public final class Cluster {
         private String keyCertChainFile = null;
         private String keyFile = null;
         private String keyPassword = null;
+        private SslContext sslContext = null;
         private LoadBalancingStrategy loadBalancingStrategy = new LoadBalancingStrategy.RoundRobin();
         private AuthProperties authProps = new AuthProperties();
 
@@ -359,6 +392,16 @@ public final class Cluster {
         }
 
         /**
+         * Explicitly set the {@code SslContext} for when more flexibility is required in the configuration than is
+         * allowed by the {@link Builder}. If this value is set to something other than {@code null} then all other
+         * related SSL settings are ignored.
+         */
+        public Builder sslContext(final SslContext sslContext) {
+            this.sslContext = sslContext;
+            return this;
+        }
+
+        /**
          * File location for a SSL Certificate Chain to use when SSL is enabled. If this value is not provided and
          * SSL is enabled, the {@link TrustManager} will be established with a self-signed certificate which is NOT
          * suitable for production purposes.
@@ -596,33 +639,13 @@ public final class Cluster {
             return this;
         }
 
-        private List<InetSocketAddress> getContactPoints() {
+        List<InetSocketAddress> getContactPoints() {
             return addresses.stream().map(addy -> new InetSocketAddress(addy, port)).collect(Collectors.toList());
         }
 
         public Cluster create() {
             if (addresses.size() == 0) addContactPoint("localhost");
-            final Settings.ConnectionPoolSettings connectionPoolSettings = new Settings.ConnectionPoolSettings();
-            connectionPoolSettings.maxInProcessPerConnection = this.maxInProcessPerConnection;
-            connectionPoolSettings.minInProcessPerConnection = this.minInProcessPerConnection;
-            connectionPoolSettings.maxSimultaneousUsagePerConnection = this.maxSimultaneousUsagePerConnection;
-            connectionPoolSettings.minSimultaneousUsagePerConnection = this.minSimultaneousUsagePerConnection;
-            connectionPoolSettings.maxSize = this.maxConnectionPoolSize;
-            connectionPoolSettings.minSize = this.minConnectionPoolSize;
-            connectionPoolSettings.maxWaitForConnection = this.maxWaitForConnection;
-            connectionPoolSettings.maxWaitForSessionClose = this.maxWaitForSessionClose;
-            connectionPoolSettings.maxContentLength = this.maxContentLength;
-            connectionPoolSettings.reconnectInitialDelay = this.reconnectInitialDelay;
-            connectionPoolSettings.reconnectInterval = this.reconnectInterval;
-            connectionPoolSettings.resultIterationBatchSize = this.resultIterationBatchSize;
-            connectionPoolSettings.enableSsl = this.enableSsl;
-            connectionPoolSettings.trustCertChainFile = this.trustCertChainFile;
-            connectionPoolSettings.keyCertChainFile = this.keyCertChainFile;
-            connectionPoolSettings.keyFile = this.keyFile;
-            connectionPoolSettings.keyPassword = this.keyPassword;
-            connectionPoolSettings.channelizer = this.channelizer;
-            return new Cluster(getContactPoints(), serializer, this.nioPoolSize, this.workerPoolSize,
-                    connectionPoolSettings, loadBalancingStrategy, authProps);
+            return new Cluster(this);
         }
     }
 
@@ -654,22 +677,42 @@ public final class Cluster {
         private final Settings.ConnectionPoolSettings connectionPoolSettings;
         private final LoadBalancingStrategy loadBalancingStrategy;
         private final AuthProperties authProps;
+        private final Optional<SslContext> sslContextOptional;
 
         private final ScheduledExecutorService executor;
 
         private final AtomicReference<CompletableFuture<Void>> closeFuture = new AtomicReference<>();
 
-        private Manager(final List<InetSocketAddress> contactPoints, final MessageSerializer serializer,
-                        final int nioPoolSize, final int workerPoolSize, final Settings.ConnectionPoolSettings connectionPoolSettings,
-                        final LoadBalancingStrategy loadBalancingStrategy,
-                        final AuthProperties authProps) {
-            this.loadBalancingStrategy = loadBalancingStrategy;
-            this.authProps = authProps;
-            this.contactPoints = contactPoints;
-            this.connectionPoolSettings = connectionPoolSettings;
-            this.factory = new Factory(nioPoolSize);
-            this.serializer = serializer;
-            this.executor = Executors.newScheduledThreadPool(workerPoolSize,
+        private Manager(final Builder builder) {
+            this.loadBalancingStrategy = builder.loadBalancingStrategy;
+            this.authProps = builder.authProps;
+            this.contactPoints = builder.getContactPoints();
+
+            connectionPoolSettings = new Settings.ConnectionPoolSettings();
+            connectionPoolSettings.maxInProcessPerConnection = builder.maxInProcessPerConnection;
+            connectionPoolSettings.minInProcessPerConnection = builder.minInProcessPerConnection;
+            connectionPoolSettings.maxSimultaneousUsagePerConnection = builder.maxSimultaneousUsagePerConnection;
+            connectionPoolSettings.minSimultaneousUsagePerConnection = builder.minSimultaneousUsagePerConnection;
+            connectionPoolSettings.maxSize = builder.maxConnectionPoolSize;
+            connectionPoolSettings.minSize = builder.minConnectionPoolSize;
+            connectionPoolSettings.maxWaitForConnection = builder.maxWaitForConnection;
+            connectionPoolSettings.maxWaitForSessionClose = builder.maxWaitForSessionClose;
+            connectionPoolSettings.maxContentLength = builder.maxContentLength;
+            connectionPoolSettings.reconnectInitialDelay = builder.reconnectInitialDelay;
+            connectionPoolSettings.reconnectInterval = builder.reconnectInterval;
+            connectionPoolSettings.resultIterationBatchSize = builder.resultIterationBatchSize;
+            connectionPoolSettings.enableSsl = builder.enableSsl;
+            connectionPoolSettings.trustCertChainFile = builder.trustCertChainFile;
+            connectionPoolSettings.keyCertChainFile = builder.keyCertChainFile;
+            connectionPoolSettings.keyFile = builder.keyFile;
+            connectionPoolSettings.keyPassword = builder.keyPassword;
+            connectionPoolSettings.channelizer = builder.channelizer;
+
+            sslContextOptional = Optional.ofNullable(builder.sslContext);
+
+            this.factory = new Factory(builder.nioPoolSize);
+            this.serializer = builder.serializer;
+            this.executor = Executors.newScheduledThreadPool(builder.workerPoolSize,
                     new BasicThreadFactory.Builder().namingPattern("gremlin-driver-worker-%d").build());
         }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/99960661/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index fdcf358..ed42d53 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -19,6 +19,10 @@
 package org.apache.tinkerpop.gremlin.server;
 
 import java.io.File;
+
+import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.SslProvider;
+import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
 import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.log4j.Logger;
 import org.apache.tinkerpop.gremlin.driver.Client;
@@ -122,6 +126,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
                 break;
             case "shouldEnableSsl":
             case "shouldEnableSslButFailIfClientConnectsWithoutIt":
+            case "shouldEnableSslWithSslContextProgrammaticallySpecified":
                 settings.ssl = new Settings.SslSettings();
                 settings.ssl.enabled = true;
                 break;
@@ -272,6 +277,24 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
     }
 
     @Test
+    public void shouldEnableSslWithSslContextProgrammaticallySpecified() throws Exception {
+        // just for testing - this is not good for production use
+        final SslContextBuilder builder = SslContextBuilder.forClient();
+        builder.trustManager(InsecureTrustManagerFactory.INSTANCE);
+        builder.sslProvider(SslProvider.JDK);
+
+        final Cluster cluster = Cluster.build().enableSsl(true).sslContext(builder.build()).create();
+        final Client client = cluster.connect();
+
+        try {
+            // this should return "nothing" - there should be no exception
+            assertEquals("test", client.submit("'test'").one().getString());
+        } finally {
+            cluster.close();
+        }
+    }
+
+    @Test
     public void shouldEnableSslButFailIfClientConnectsWithoutIt() {
         final Cluster cluster = Cluster.build().enableSsl(false).create();
         final Client client = cluster.connect();

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/99960661/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
index 208aaef..15b2c4b 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
@@ -119,6 +119,7 @@ public class GremlinServerSessionIntegrateTest  extends AbstractGremlinServerInt
             fail("Should have tossed the manually generated exception");
         } catch (Exception ex) {
             final Throwable root = ExceptionUtils.getRootCause(ex);
+            ex.printStackTrace();
             assertEquals("no worky", root.getMessage());
 
             // just force a commit here of "something" in case there is something lingering


[3/6] incubator-tinkerpop git commit: Added docs for new SSL settings on the driver side.

Posted by sp...@apache.org.
Added docs for new SSL settings on the driver side.


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

Branch: refs/heads/TINKERPOP-1269
Commit: cfa95c8a29b4e27c9fd8e047a5e3631f915de005
Parents: 5741616
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Apr 19 14:02:12 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Apr 20 15:07:15 2016 -0400

----------------------------------------------------------------------
 docs/src/reference/gremlin-applications.asciidoc | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cfa95c8a/docs/src/reference/gremlin-applications.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index 9beae1f..410dfe1 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -610,6 +610,9 @@ The following table describes the various configuration options for the Gremlin
 |Key |Description |Default
 |connectionPool.channelizer |The fully qualified classname of the client `Channelizer` that defines how to connect to the server. |`Channelizer.WebSocketChannelizer`
 |connectionPool.enableSsl |Determines if SSL should be enabled or not. If enabled on the server then it must be enabled on the client. |false
+|connectionPool.keyCertChainFile |The X.509 certificate chain file in PEM format. |_none_
+|connectionPool.keyFile |The `PKCS#8` private key file in PEM format. |_none_
+|connectionPool.keyPassword |The password of the `keyFile` if it's not password-protected |_none_
 |connectionPool.maxContentLength |The maximum length in bytes that a message can be sent to the server. This number can be no greater than the setting of the same name in the server configuration. |65536
 |connectionPool.maxInProcessPerConnection |The maximum number of in-flight requests that can occur on a connection. |4
 |connectionPool.maxSimultaneousUsagePerConnection |The maximum number of times that a connection can be borrowed from the pool simultaneously. |16


[2/6] incubator-tinkerpop git commit: Minor fixes to session tests for Gremlin Server CTR

Posted by sp...@apache.org.
Minor fixes to session tests for Gremlin Server CTR


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

Branch: refs/heads/TINKERPOP-1269
Commit: ec730eb774c8e17475fc813a89ff5b9c488fa12b
Parents: 3a4e2af
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Apr 20 15:05:22 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Apr 20 15:05:22 2016 -0400

----------------------------------------------------------------------
 .../gremlin/server/GremlinServerSessionIntegrateTest.java       | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/ec730eb7/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
index 56336fa..208aaef 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerSessionIntegrateTest.java
@@ -44,6 +44,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.IntStream;
 
@@ -108,6 +109,8 @@ public class GremlinServerSessionIntegrateTest  extends AbstractGremlinServerInt
 
     @Test
     public void shouldRollbackOnEvalExceptionForManagedTransaction() throws Exception {
+        assumeNeo4jIsPresent();
+
         final Cluster cluster = Cluster.build().create();
         final Client client = cluster.connect(name.getMethodName(), true);
 
@@ -215,7 +218,7 @@ public class GremlinServerSessionIntegrateTest  extends AbstractGremlinServerInt
         assertEquals(requests, futures.size());
 
         for(CompletableFuture<ResultSet> f : futures) {
-            final Result r = f.get().one();
+            final Result r = f.get().all().get(3000, TimeUnit.MILLISECONDS).get(0);
             assertEquals(11100, r.getInt());
         }
 


[6/6] incubator-tinkerpop git commit: Added configuration for overriding the Gremlin Server SSL config with SslContext.

Posted by sp...@apache.org.
Added configuration for overriding the Gremlin Server SSL config with SslContext.


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

Branch: refs/heads/TINKERPOP-1269
Commit: 75e875700201013df7b2323a7a11907c0b9ce500
Parents: 9996066
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Wed Apr 20 16:13:24 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Apr 20 16:13:24 2016 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 .../tinkerpop/gremlin/driver/Cluster.java       |   3 +-
 .../gremlin/server/AbstractChannelizer.java     |   6 +
 .../tinkerpop/gremlin/server/Settings.java      |  16 +
 .../server/GremlinServerIntegrateTest.java      | 853 ++++++++++---------
 5 files changed, 461 insertions(+), 418 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/75e87570/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 32b534d..c2ae91d 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/incubator-tinkerpop/master/docs/
 TinkerPop 3.1.3 (NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Added configuration options to Gremlin Driver and Server to override the SSL configuration with an `SslContext`.
 * Added driver configuration settings for SSL: `keyCertChainFile`, `keyFile` and `keyPassword`.
 * Fixed bug where transaction managed sessions were not properly rolling back transactions for exceptions encountered during script evaluation.
 * Fixed bug in `:uninstall` command if the default `/ext` directory was not used.

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/75e87570/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
index 3fa11f7..f033dc3 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
@@ -394,7 +394,8 @@ public final class Cluster {
         /**
          * Explicitly set the {@code SslContext} for when more flexibility is required in the configuration than is
          * allowed by the {@link Builder}. If this value is set to something other than {@code null} then all other
-         * related SSL settings are ignored.
+         * related SSL settings are ignored. The {@link #enableSsl} setting should still be set to {@code true} for
+         * this setting to take effect.
          */
         public Builder sslContext(final SslContext sslContext) {
             this.sslContext = sslContext;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/75e87570/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java
index 41d909e..829a3ee 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java
@@ -195,6 +195,12 @@ public abstract class AbstractChannelizer extends ChannelInitializer<SocketChann
 
     private SslContext createSSLContext(final Settings settings)  {
         final Settings.SslSettings sslSettings = settings.ssl;
+
+        if (sslSettings.getSslContext().isPresent()) {
+            logger.info("Using the SslContext override");
+            return sslSettings.getSslContext().get();
+        }
+
         final SslProvider provider = SslProvider.JDK;
 
         final SslContextBuilder builder;

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/75e87570/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
index a6f59cd..b5d69f0 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
@@ -18,6 +18,7 @@
  */
 package org.apache.tinkerpop.gremlin.server;
 
+import io.netty.handler.ssl.SslContext;
 import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
 import org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV1d0;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
@@ -406,6 +407,21 @@ public class Settings {
          * contain an X.509 certificate chain in PEM format. {@code null} uses the system default.
          */
         public String trustCertChainFile = null;
+
+        private SslContext sslContext;
+
+        /**
+         * When this value is set, the other settings for SSL are ignored. This option provides for a programmatic
+         * way to configure more complex SSL configurations. The {@link #enabled} setting should still be set to
+         * {@code true} for this setting to take effect.
+         */
+        public void overrideSslContext(final SslContext sslContext) {
+            this.sslContext = sslContext;
+        }
+
+        public Optional<SslContext> getSslContext() {
+            return Optional.ofNullable(sslContext);
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/75e87570/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index ed42d53..c438e63 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -20,9 +20,11 @@ package org.apache.tinkerpop.gremlin.server;
 
 import java.io.File;
 
+import io.netty.handler.ssl.SslContext;
 import io.netty.handler.ssl.SslContextBuilder;
 import io.netty.handler.ssl.SslProvider;
 import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
+import io.netty.handler.ssl.util.SelfSignedCertificate;
 import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.log4j.Logger;
 import org.apache.tinkerpop.gremlin.driver.Client;
@@ -53,6 +55,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 import java.nio.channels.ClosedChannelException;
+import java.security.cert.CertificateException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -126,9 +129,13 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
                 break;
             case "shouldEnableSsl":
             case "shouldEnableSslButFailIfClientConnectsWithoutIt":
+                settings.ssl = new Settings.SslSettings();
+                settings.ssl.enabled = true;
+                break;
             case "shouldEnableSslWithSslContextProgrammaticallySpecified":
                 settings.ssl = new Settings.SslSettings();
                 settings.ssl.enabled = true;
+                settings.ssl.overrideSslContext(createServerSslContext());
                 break;
             case "shouldStartWithDefaultSettings":
                 return new Settings();
@@ -159,6 +166,18 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
         return settings;
     }
 
+    private static SslContext createServerSslContext() {
+        final SslProvider provider = SslProvider.JDK;
+
+        try {
+            // this is not good for production - just testing
+            final SelfSignedCertificate ssc = new SelfSignedCertificate();
+            return SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).sslProvider(provider).build();
+        } catch (Exception ce) {
+            throw new RuntimeException("Couldn't setup self-signed certificate for test");
+        }
+    }
+
     private static Map<String, Object> getScriptEngineConfForSimpleSandbox() {
         final Map<String,Object> scriptEngineConf = new HashMap<>();
         final Map<String,Object> compilerCustomizerProviderConf = new HashMap<>();
@@ -310,421 +329,421 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
         }
     }
 
-    @Test
-    public void shouldRespectHighWaterMarkSettingAndSucceed() throws Exception {
-        // the highwatermark should get exceeded on the server and thus pause the writes, but have no problem catching
-        // itself up - this is a tricky tests to get passing on all environments so this assumption will deny the
-        // test for most cases
-        assumeThat("Set the 'assertNonDeterministic' property to true to execute this test",
-                System.getProperty("assertNonDeterministic"), is("true"));
-
-        final Cluster cluster = Cluster.open();
-        final Client client = cluster.connect();
-
-        try {
-            final int resultCountToGenerate = 1000;
-            final int batchSize = 3;
-            final String fatty = IntStream.range(0, 175).mapToObj(String::valueOf).collect(Collectors.joining());
-            final String fattyX = "['" + fatty + "'] * " + resultCountToGenerate;
-
-            // don't allow the thread to proceed until all results are accounted for
-            final CountDownLatch latch = new CountDownLatch(resultCountToGenerate);
-            final AtomicBoolean expected = new AtomicBoolean(false);
-            final AtomicBoolean faulty = new AtomicBoolean(false);
-            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
-                    .addArg(Tokens.ARGS_BATCH_SIZE, batchSize)
-                    .addArg(Tokens.ARGS_GREMLIN, fattyX).create();
-
-            client.submitAsync(request).thenAcceptAsync(r -> {
-                r.stream().forEach(item -> {
-                    try {
-                        final String aFattyResult = item.getString();
-                        expected.set(aFattyResult.equals(fatty));
-                    } catch (Exception ex) {
-                        ex.printStackTrace();
-                        faulty.set(true);
-                    } finally {
-                        latch.countDown();
-                    }
-                });
-            });
-
-            assertTrue(latch.await(30000, TimeUnit.MILLISECONDS));
-            assertEquals(0, latch.getCount());
-            assertFalse(faulty.get());
-            assertTrue(expected.get());
-
-            assertTrue(recordingAppender.getMessages().stream().anyMatch(m -> m.contains("Pausing response writing as writeBufferHighWaterMark exceeded on")));
-        } catch (Exception ex) {
-            fail("Shouldn't have tossed an exception");
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @Test
-    public void shouldReturnInvalidRequestArgsWhenGremlinArgIsNotSupplied() throws Exception {
-        try (SimpleClient client = new WebSocketClient()) {
-            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL).create();
-            final ResponseMessage result = client.submit(request).get(0);
-            assertThat(result.getStatus().getCode(), is(not(ResponseStatusCode.PARTIAL_CONTENT)));
-            assertEquals(result.getStatus().getCode(), ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS);
-        }
-    }
-
-    @Test
-    public void shouldReturnInvalidRequestArgsWhenInvalidReservedBindingKeyIsUsed() throws Exception {
-        try (SimpleClient client = new WebSocketClient()) {
-            final Map<String, Object> bindings = new HashMap<>();
-            bindings.put(T.id.getAccessor(), "123");
-            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
-                    .addArg(Tokens.ARGS_GREMLIN, "[1,2,3,4,5,6,7,8,9,0]")
-                    .addArg(Tokens.ARGS_BINDINGS, bindings).create();
-            final CountDownLatch latch = new CountDownLatch(1);
-            final AtomicBoolean pass = new AtomicBoolean(false);
-            client.submit(request, result -> {
-                if (result.getStatus().getCode() != ResponseStatusCode.PARTIAL_CONTENT) {
-                    pass.set(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS == result.getStatus().getCode());
-                    latch.countDown();
-                }
-            });
-
-            if (!latch.await(3000, TimeUnit.MILLISECONDS))
-                fail("Request should have returned error, but instead timed out");
-            assertTrue(pass.get());
-        }
-    }
-
-    @Test
-    public void shouldReturnInvalidRequestArgsWhenInvalidTypeBindingKeyIsUsed() throws Exception {
-        try (SimpleClient client = new WebSocketClient()) {
-            final Map<Object, Object> bindings = new HashMap<>();
-            bindings.put(1, "123");
-            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
-                    .addArg(Tokens.ARGS_GREMLIN, "[1,2,3,4,5,6,7,8,9,0]")
-                    .addArg(Tokens.ARGS_BINDINGS, bindings).create();
-            final CountDownLatch latch = new CountDownLatch(1);
-            final AtomicBoolean pass = new AtomicBoolean(false);
-            client.submit(request, result -> {
-                if (result.getStatus().getCode() != ResponseStatusCode.PARTIAL_CONTENT) {
-                    pass.set(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS == result.getStatus().getCode());
-                    latch.countDown();
-                }
-            });
-
-            if (!latch.await(3000, TimeUnit.MILLISECONDS))
-                fail("Request should have returned error, but instead timed out");
-            assertTrue(pass.get());
-        }
-    }
-
-    @Test
-    public void shouldReturnInvalidRequestArgsWhenInvalidNullBindingKeyIsUsed() throws Exception {
-        try (SimpleClient client = new WebSocketClient()) {
-            final Map<String, Object> bindings = new HashMap<>();
-            bindings.put(null, "123");
-            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
-                    .addArg(Tokens.ARGS_GREMLIN, "[1,2,3,4,5,6,7,8,9,0]")
-                    .addArg(Tokens.ARGS_BINDINGS, bindings).create();
-            final CountDownLatch latch = new CountDownLatch(1);
-            final AtomicBoolean pass = new AtomicBoolean(false);
-            client.submit(request, result -> {
-                if (result.getStatus().getCode() != ResponseStatusCode.PARTIAL_CONTENT) {
-                    pass.set(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS == result.getStatus().getCode());
-                    latch.countDown();
-                }
-            });
-
-            if (!latch.await(3000, TimeUnit.MILLISECONDS))
-                fail("Request should have returned error, but instead timed out");
-            assertTrue(pass.get());
-        }
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void shouldBatchResultsByTwos() throws Exception {
-        try (SimpleClient client = new WebSocketClient()) {
-            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
-                    .addArg(Tokens.ARGS_GREMLIN, "[0,1,2,3,4,5,6,7,8,9]").create();
-
-            final List<ResponseMessage> msgs = client.submit(request);
-            assertEquals(5, client.submit(request).size());
-            assertEquals(0, ((List<Integer>) msgs.get(0).getResult().getData()).get(0).intValue());
-            assertEquals(1, ((List<Integer>) msgs.get(0).getResult().getData()).get(1).intValue());
-            assertEquals(2, ((List<Integer>) msgs.get(1).getResult().getData()).get(0).intValue());
-            assertEquals(3, ((List<Integer>) msgs.get(1).getResult().getData()).get(1).intValue());
-            assertEquals(4, ((List<Integer>) msgs.get(2).getResult().getData()).get(0).intValue());
-            assertEquals(5, ((List<Integer>) msgs.get(2).getResult().getData()).get(1).intValue());
-            assertEquals(6, ((List<Integer>) msgs.get(3).getResult().getData()).get(0).intValue());
-            assertEquals(7, ((List<Integer>) msgs.get(3).getResult().getData()).get(1).intValue());
-            assertEquals(8, ((List<Integer>) msgs.get(4).getResult().getData()).get(0).intValue());
-            assertEquals(9, ((List<Integer>) msgs.get(4).getResult().getData()).get(1).intValue());
-        }
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void shouldBatchResultsByOnesByOverridingFromClientSide() throws Exception {
-        try (SimpleClient client = new WebSocketClient()) {
-            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
-                    .addArg(Tokens.ARGS_GREMLIN, "[0,1,2,3,4,5,6,7,8,9]")
-                    .addArg(Tokens.ARGS_BATCH_SIZE, 1).create();
-
-            final List<ResponseMessage> msgs = client.submit(request);
-            assertEquals(10, msgs.size());
-            IntStream.rangeClosed(0, 9).forEach(i -> assertEquals(i, ((List<Integer>) msgs.get(i).getResult().getData()).get(0).intValue()));
-        }
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void shouldWorkOverNioTransport() throws Exception {
-        try (SimpleClient client = new NioClient()) {
-            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
-                    .addArg(Tokens.ARGS_GREMLIN, "[0,1,2,3,4,5,6,7,8,9,]").create();
-
-            final List<ResponseMessage> msg = client.submit(request);
-            assertEquals(1, msg.size());
-            final List<Integer> integers = (List<Integer>) msg.get(0).getResult().getData();
-            IntStream.rangeClosed(0, 9).forEach(i -> assertEquals(i, integers.get(i).intValue()));
-        }
-    }
-
-    @Test
-    public void shouldNotThrowNoSuchElementException() throws Exception {
-        try (SimpleClient client = new WebSocketClient()){
-            // this should return "nothing" - there should be no exception
-            final List<ResponseMessage> responses = client.submit("g.V().has('name','kadfjaldjfla')");
-            assertNull(responses.get(0).getResult().getData());
-        }
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void shouldReceiveFailureTimeOutOnScriptEval() throws Exception {
-        try (SimpleClient client = new WebSocketClient()){
-            final List<ResponseMessage> responses = client.submit("Thread.sleep(3000);'some-stuff-that-should not return'");
-            assertThat(responses.get(0).getStatus().getMessage(), startsWith("Script evaluation exceeded the configured 'scriptEvaluationTimeout' threshold of 200 ms for request"));
-
-            // validate that we can still send messages to the server
-            assertEquals(2, ((List<Integer>) client.submit("1+1").get(0).getResult().getData()).get(0).intValue());
-        }
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void shouldReceiveFailureTimeOutOnScriptEvalUsingOverride() throws Exception {
-        try (SimpleClient client = new WebSocketClient()) {
-            final RequestMessage msg = RequestMessage.build("eval")
-                    .addArg(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT, 100)
-                    .addArg(Tokens.ARGS_GREMLIN, "Thread.sleep(3000);'some-stuff-that-should not return'")
-                    .create();
-            final List<ResponseMessage> responses = client.submit(msg);
-            assertThat(responses.get(0).getStatus().getMessage(), startsWith("Script evaluation exceeded the configured 'scriptEvaluationTimeout' threshold of 100 ms for request"));
-
-            // validate that we can still send messages to the server
-            assertEquals(2, ((List<Integer>) client.submit("1+1").get(0).getResult().getData()).get(0).intValue());
-        }
-    }
-
-    @Test
-    public void shouldReceiveFailureTimeOutOnScriptEvalOfOutOfControlLoop() throws Exception {
-        try (SimpleClient client = new WebSocketClient()){
-            // timeout configured for 1 second so the timed interrupt should trigger prior to the
-            // scriptEvaluationTimeout which is at 30 seconds by default
-            final List<ResponseMessage> responses = client.submit("while(true){}");
-            assertThat(responses.get(0).getStatus().getMessage(), startsWith("Timeout during script evaluation triggered by TimedInterruptCustomizerProvider"));
-
-            // validate that we can still send messages to the server
-            assertEquals(2, ((List<Integer>) client.submit("1+1").get(0).getResult().getData()).get(0).intValue());
-        }
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void shouldReceiveFailureTimeOutOnTotalSerialization() throws Exception {
-        try (SimpleClient client = new WebSocketClient()){
-            final List<ResponseMessage> responses = client.submit("(0..<100000)");
-
-            // the last message should contain the error
-            assertThat(responses.get(responses.size() - 1).getStatus().getMessage(), endsWith("Serialization of the entire response exceeded the 'serializeResponseTimeout' setting"));
-
-            // validate that we can still send messages to the server
-            assertEquals(2, ((List<Integer>) client.submit("1+1").get(0).getResult().getData()).get(0).intValue());
-        }
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void shouldLoadInitScript() throws Exception {
-        try (SimpleClient client = new WebSocketClient()){
-            assertEquals(2, ((List<Integer>) client.submit("addItUp(1,1)").get(0).getResult().getData()).get(0).intValue());
-        }
-    }
-
-    @Test
-    public void shouldGarbageCollectPhantomButNotHard() throws Exception {
-        final Cluster cluster = Cluster.open();
-        final Client client = cluster.connect();
-
-        assertEquals(2, client.submit("addItUp(1,1)").all().join().get(0).getInt());
-        assertEquals(0, client.submit("def subtract(x,y){x-y};subtract(1,1)").all().join().get(0).getInt());
-        assertEquals(0, client.submit("subtract(1,1)").all().join().get(0).getInt());
-
-        final Map<String, Object> bindings = new HashMap<>();
-        bindings.put(GremlinGroovyScriptEngine.KEY_REFERENCE_TYPE, GremlinGroovyScriptEngine.REFERENCE_TYPE_PHANTOM);
-        assertEquals(4, client.submit("def multiply(x,y){x*y};multiply(2,2)", bindings).all().join().get(0).getInt());
-
-        try {
-            client.submit("multiply(2,2)").all().join().get(0).getInt();
-            fail("Should throw an exception since reference is phantom.");
-        } catch (RuntimeException ignored) {
-
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @Test
-    public void shouldReceiveFailureOnBadGraphSONSerialization() throws Exception {
-        final Cluster cluster = Cluster.build("localhost").serializer(Serializers.GRAPHSON_V1D0).create();
-        final Client client = cluster.connect();
-
-        try {
-            client.submit("def class C { def C getC(){return this}}; new C()").all().join();
-            fail("Should throw an exception.");
-        } catch (RuntimeException re) {
-            final Throwable root = ExceptionUtils.getRootCause(re);
-            assertThat(root.getMessage(), CoreMatchers.startsWith("Error during serialization: Direct self-reference leading to cycle (through reference chain:"));
-
-            // validate that we can still send messages to the server
-            assertEquals(2, client.submit("1+1").all().join().get(0).getInt());
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @Test
-    public void shouldReceiveFailureOnBadGryoSerialization() throws Exception {
-        final Cluster cluster = Cluster.build("localhost").serializer(Serializers.GRYO_V1D0).create();
-        final Client client = cluster.connect();
-
-        try {
-            client.submit("java.awt.Color.RED").all().join();
-            fail("Should throw an exception.");
-        } catch (RuntimeException re) {
-            final Throwable root = ExceptionUtils.getRootCause(re);
-            assertThat(root.getMessage(), CoreMatchers.startsWith("Error during serialization: Class is not registered: java.awt.Color"));
-
-            // validate that we can still send messages to the server
-            assertEquals(2, client.submit("1+1").all().join().get(0).getInt());
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
-    @Test
-    public void shouldBlockRequestWhenTooBig() throws Exception {
-        final Cluster cluster = Cluster.open();
-        final Client client = cluster.connect();
-
-        try {
-            final String fatty = IntStream.range(0, 1024).mapToObj(String::valueOf).collect(Collectors.joining());
-            final CompletableFuture<ResultSet> result = client.submitAsync("'" + fatty + "';'test'");
-            final ResultSet resultSet = result.get(10000, TimeUnit.MILLISECONDS);
-            resultSet.all().get(10000, TimeUnit.MILLISECONDS);
-            fail("Should throw an exception.");
-        } catch (TimeoutException te) {
-            // the request should not have timed-out - the connection should have been reset, but it seems that
-            // timeout seems to occur as well on some systems (it's not clear why).  however, the nature of this
-            // test is to ensure that the script isn't processed if it exceeds a certain size, so in this sense
-            // it seems ok to pass in this case.
-        } catch (Exception re) {
-            final Throwable root = ExceptionUtils.getRootCause(re);
-            assertEquals("Connection reset by peer", root.getMessage());
-
-            // validate that we can still send messages to the server
-            assertEquals(2, client.submit("1+1").all().join().get(0).getInt());
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @Test
-    public void shouldFailOnDeadHost() throws Exception {
-        final Cluster cluster = Cluster.build("localhost").create();
-        final Client client = cluster.connect();
-
-        // ensure that connection to server is good
-        assertEquals(2, client.submit("1+1").all().join().get(0).getInt());
-
-        // kill the server which will make the client mark the host as unavailable
-        this.stopServer();
-
-        try {
-            // try to re-issue a request now that the server is down
-            client.submit("1+1").all().join();
-            fail();
-        } catch (RuntimeException re) {
-            assertTrue(re.getCause().getCause() instanceof ClosedChannelException);
-
-            //
-            // should recover when the server comes back
-            //
-
-            // restart server
-            this.startServer();
-            // the retry interval is 1 second, wait a bit longer
-            TimeUnit.SECONDS.sleep(5);
-
-            List<Result> results = client.submit("1+1").all().join();
-            assertEquals(1, results.size());
-            assertEquals(2, results.get(0).getInt());
-
-        } finally {
-            cluster.close();
-        }
-    }
-
-    @Test
-    public void shouldNotHavePartialContentWithOneResult() throws Exception {
-        try (SimpleClient client = new WebSocketClient()) {
-            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
-                    .addArg(Tokens.ARGS_GREMLIN, "10").create();
-            final List<ResponseMessage> responses = client.submit(request);
-            assertEquals(1, responses.size());
-            assertEquals(ResponseStatusCode.SUCCESS, responses.get(0).getStatus().getCode());
-        }
-    }
-
-    @Test
-    public void shouldFailWithBadScriptEval() throws Exception {
-        try (SimpleClient client = new WebSocketClient()) {
-            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
-                    .addArg(Tokens.ARGS_GREMLIN, "new String().doNothingAtAllBecauseThis is a syntax error").create();
-            final List<ResponseMessage> responses = client.submit(request);
-            assertEquals(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION, responses.get(0).getStatus().getCode());
-            assertEquals(1, responses.size());
-        }
-    }
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void shouldStillSupportDeprecatedRebindingsParameterOnServer() throws Exception {
-        // this test can be removed when the rebindings arg is removed
-        try (SimpleClient client = new WebSocketClient()) {
-            final Map<String,String> rebindings = new HashMap<>();
-            rebindings.put("xyz", "graph");
-            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
-                    .addArg(Tokens.ARGS_GREMLIN, "xyz.addVertex('name','jason')")
-                    .addArg(Tokens.ARGS_REBINDINGS, rebindings).create();
-            final List<ResponseMessage> responses = client.submit(request);
-            assertEquals(1, responses.size());
-
-            final DetachedVertex v = ((ArrayList<DetachedVertex>) responses.get(0).getResult().getData()).get(0);
-            assertEquals("jason", v.value("name"));
-        }
-    }
+//    @Test
+//    public void shouldRespectHighWaterMarkSettingAndSucceed() throws Exception {
+//        // the highwatermark should get exceeded on the server and thus pause the writes, but have no problem catching
+//        // itself up - this is a tricky tests to get passing on all environments so this assumption will deny the
+//        // test for most cases
+//        assumeThat("Set the 'assertNonDeterministic' property to true to execute this test",
+//                System.getProperty("assertNonDeterministic"), is("true"));
+//
+//        final Cluster cluster = Cluster.open();
+//        final Client client = cluster.connect();
+//
+//        try {
+//            final int resultCountToGenerate = 1000;
+//            final int batchSize = 3;
+//            final String fatty = IntStream.range(0, 175).mapToObj(String::valueOf).collect(Collectors.joining());
+//            final String fattyX = "['" + fatty + "'] * " + resultCountToGenerate;
+//
+//            // don't allow the thread to proceed until all results are accounted for
+//            final CountDownLatch latch = new CountDownLatch(resultCountToGenerate);
+//            final AtomicBoolean expected = new AtomicBoolean(false);
+//            final AtomicBoolean faulty = new AtomicBoolean(false);
+//            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+//                    .addArg(Tokens.ARGS_BATCH_SIZE, batchSize)
+//                    .addArg(Tokens.ARGS_GREMLIN, fattyX).create();
+//
+//            client.submitAsync(request).thenAcceptAsync(r -> {
+//                r.stream().forEach(item -> {
+//                    try {
+//                        final String aFattyResult = item.getString();
+//                        expected.set(aFattyResult.equals(fatty));
+//                    } catch (Exception ex) {
+//                        ex.printStackTrace();
+//                        faulty.set(true);
+//                    } finally {
+//                        latch.countDown();
+//                    }
+//                });
+//            });
+//
+//            assertTrue(latch.await(30000, TimeUnit.MILLISECONDS));
+//            assertEquals(0, latch.getCount());
+//            assertFalse(faulty.get());
+//            assertTrue(expected.get());
+//
+//            assertTrue(recordingAppender.getMessages().stream().anyMatch(m -> m.contains("Pausing response writing as writeBufferHighWaterMark exceeded on")));
+//        } catch (Exception ex) {
+//            fail("Shouldn't have tossed an exception");
+//        } finally {
+//            cluster.close();
+//        }
+//    }
+//
+//    @Test
+//    public void shouldReturnInvalidRequestArgsWhenGremlinArgIsNotSupplied() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()) {
+//            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL).create();
+//            final ResponseMessage result = client.submit(request).get(0);
+//            assertThat(result.getStatus().getCode(), is(not(ResponseStatusCode.PARTIAL_CONTENT)));
+//            assertEquals(result.getStatus().getCode(), ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS);
+//        }
+//    }
+//
+//    @Test
+//    public void shouldReturnInvalidRequestArgsWhenInvalidReservedBindingKeyIsUsed() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()) {
+//            final Map<String, Object> bindings = new HashMap<>();
+//            bindings.put(T.id.getAccessor(), "123");
+//            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+//                    .addArg(Tokens.ARGS_GREMLIN, "[1,2,3,4,5,6,7,8,9,0]")
+//                    .addArg(Tokens.ARGS_BINDINGS, bindings).create();
+//            final CountDownLatch latch = new CountDownLatch(1);
+//            final AtomicBoolean pass = new AtomicBoolean(false);
+//            client.submit(request, result -> {
+//                if (result.getStatus().getCode() != ResponseStatusCode.PARTIAL_CONTENT) {
+//                    pass.set(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS == result.getStatus().getCode());
+//                    latch.countDown();
+//                }
+//            });
+//
+//            if (!latch.await(3000, TimeUnit.MILLISECONDS))
+//                fail("Request should have returned error, but instead timed out");
+//            assertTrue(pass.get());
+//        }
+//    }
+//
+//    @Test
+//    public void shouldReturnInvalidRequestArgsWhenInvalidTypeBindingKeyIsUsed() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()) {
+//            final Map<Object, Object> bindings = new HashMap<>();
+//            bindings.put(1, "123");
+//            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+//                    .addArg(Tokens.ARGS_GREMLIN, "[1,2,3,4,5,6,7,8,9,0]")
+//                    .addArg(Tokens.ARGS_BINDINGS, bindings).create();
+//            final CountDownLatch latch = new CountDownLatch(1);
+//            final AtomicBoolean pass = new AtomicBoolean(false);
+//            client.submit(request, result -> {
+//                if (result.getStatus().getCode() != ResponseStatusCode.PARTIAL_CONTENT) {
+//                    pass.set(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS == result.getStatus().getCode());
+//                    latch.countDown();
+//                }
+//            });
+//
+//            if (!latch.await(3000, TimeUnit.MILLISECONDS))
+//                fail("Request should have returned error, but instead timed out");
+//            assertTrue(pass.get());
+//        }
+//    }
+//
+//    @Test
+//    public void shouldReturnInvalidRequestArgsWhenInvalidNullBindingKeyIsUsed() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()) {
+//            final Map<String, Object> bindings = new HashMap<>();
+//            bindings.put(null, "123");
+//            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+//                    .addArg(Tokens.ARGS_GREMLIN, "[1,2,3,4,5,6,7,8,9,0]")
+//                    .addArg(Tokens.ARGS_BINDINGS, bindings).create();
+//            final CountDownLatch latch = new CountDownLatch(1);
+//            final AtomicBoolean pass = new AtomicBoolean(false);
+//            client.submit(request, result -> {
+//                if (result.getStatus().getCode() != ResponseStatusCode.PARTIAL_CONTENT) {
+//                    pass.set(ResponseStatusCode.REQUEST_ERROR_INVALID_REQUEST_ARGUMENTS == result.getStatus().getCode());
+//                    latch.countDown();
+//                }
+//            });
+//
+//            if (!latch.await(3000, TimeUnit.MILLISECONDS))
+//                fail("Request should have returned error, but instead timed out");
+//            assertTrue(pass.get());
+//        }
+//    }
+//
+//    @Test
+//    @SuppressWarnings("unchecked")
+//    public void shouldBatchResultsByTwos() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()) {
+//            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+//                    .addArg(Tokens.ARGS_GREMLIN, "[0,1,2,3,4,5,6,7,8,9]").create();
+//
+//            final List<ResponseMessage> msgs = client.submit(request);
+//            assertEquals(5, client.submit(request).size());
+//            assertEquals(0, ((List<Integer>) msgs.get(0).getResult().getData()).get(0).intValue());
+//            assertEquals(1, ((List<Integer>) msgs.get(0).getResult().getData()).get(1).intValue());
+//            assertEquals(2, ((List<Integer>) msgs.get(1).getResult().getData()).get(0).intValue());
+//            assertEquals(3, ((List<Integer>) msgs.get(1).getResult().getData()).get(1).intValue());
+//            assertEquals(4, ((List<Integer>) msgs.get(2).getResult().getData()).get(0).intValue());
+//            assertEquals(5, ((List<Integer>) msgs.get(2).getResult().getData()).get(1).intValue());
+//            assertEquals(6, ((List<Integer>) msgs.get(3).getResult().getData()).get(0).intValue());
+//            assertEquals(7, ((List<Integer>) msgs.get(3).getResult().getData()).get(1).intValue());
+//            assertEquals(8, ((List<Integer>) msgs.get(4).getResult().getData()).get(0).intValue());
+//            assertEquals(9, ((List<Integer>) msgs.get(4).getResult().getData()).get(1).intValue());
+//        }
+//    }
+//
+//    @Test
+//    @SuppressWarnings("unchecked")
+//    public void shouldBatchResultsByOnesByOverridingFromClientSide() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()) {
+//            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+//                    .addArg(Tokens.ARGS_GREMLIN, "[0,1,2,3,4,5,6,7,8,9]")
+//                    .addArg(Tokens.ARGS_BATCH_SIZE, 1).create();
+//
+//            final List<ResponseMessage> msgs = client.submit(request);
+//            assertEquals(10, msgs.size());
+//            IntStream.rangeClosed(0, 9).forEach(i -> assertEquals(i, ((List<Integer>) msgs.get(i).getResult().getData()).get(0).intValue()));
+//        }
+//    }
+//
+//    @Test
+//    @SuppressWarnings("unchecked")
+//    public void shouldWorkOverNioTransport() throws Exception {
+//        try (SimpleClient client = new NioClient()) {
+//            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+//                    .addArg(Tokens.ARGS_GREMLIN, "[0,1,2,3,4,5,6,7,8,9,]").create();
+//
+//            final List<ResponseMessage> msg = client.submit(request);
+//            assertEquals(1, msg.size());
+//            final List<Integer> integers = (List<Integer>) msg.get(0).getResult().getData();
+//            IntStream.rangeClosed(0, 9).forEach(i -> assertEquals(i, integers.get(i).intValue()));
+//        }
+//    }
+//
+//    @Test
+//    public void shouldNotThrowNoSuchElementException() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()){
+//            // this should return "nothing" - there should be no exception
+//            final List<ResponseMessage> responses = client.submit("g.V().has('name','kadfjaldjfla')");
+//            assertNull(responses.get(0).getResult().getData());
+//        }
+//    }
+//
+//    @Test
+//    @SuppressWarnings("unchecked")
+//    public void shouldReceiveFailureTimeOutOnScriptEval() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()){
+//            final List<ResponseMessage> responses = client.submit("Thread.sleep(3000);'some-stuff-that-should not return'");
+//            assertThat(responses.get(0).getStatus().getMessage(), startsWith("Script evaluation exceeded the configured 'scriptEvaluationTimeout' threshold of 200 ms for request"));
+//
+//            // validate that we can still send messages to the server
+//            assertEquals(2, ((List<Integer>) client.submit("1+1").get(0).getResult().getData()).get(0).intValue());
+//        }
+//    }
+//
+//    @Test
+//    @SuppressWarnings("unchecked")
+//    public void shouldReceiveFailureTimeOutOnScriptEvalUsingOverride() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()) {
+//            final RequestMessage msg = RequestMessage.build("eval")
+//                    .addArg(Tokens.ARGS_SCRIPT_EVAL_TIMEOUT, 100)
+//                    .addArg(Tokens.ARGS_GREMLIN, "Thread.sleep(3000);'some-stuff-that-should not return'")
+//                    .create();
+//            final List<ResponseMessage> responses = client.submit(msg);
+//            assertThat(responses.get(0).getStatus().getMessage(), startsWith("Script evaluation exceeded the configured 'scriptEvaluationTimeout' threshold of 100 ms for request"));
+//
+//            // validate that we can still send messages to the server
+//            assertEquals(2, ((List<Integer>) client.submit("1+1").get(0).getResult().getData()).get(0).intValue());
+//        }
+//    }
+//
+//    @Test
+//    public void shouldReceiveFailureTimeOutOnScriptEvalOfOutOfControlLoop() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()){
+//            // timeout configured for 1 second so the timed interrupt should trigger prior to the
+//            // scriptEvaluationTimeout which is at 30 seconds by default
+//            final List<ResponseMessage> responses = client.submit("while(true){}");
+//            assertThat(responses.get(0).getStatus().getMessage(), startsWith("Timeout during script evaluation triggered by TimedInterruptCustomizerProvider"));
+//
+//            // validate that we can still send messages to the server
+//            assertEquals(2, ((List<Integer>) client.submit("1+1").get(0).getResult().getData()).get(0).intValue());
+//        }
+//    }
+//
+//    @Test
+//    @SuppressWarnings("unchecked")
+//    public void shouldReceiveFailureTimeOutOnTotalSerialization() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()){
+//            final List<ResponseMessage> responses = client.submit("(0..<100000)");
+//
+//            // the last message should contain the error
+//            assertThat(responses.get(responses.size() - 1).getStatus().getMessage(), endsWith("Serialization of the entire response exceeded the 'serializeResponseTimeout' setting"));
+//
+//            // validate that we can still send messages to the server
+//            assertEquals(2, ((List<Integer>) client.submit("1+1").get(0).getResult().getData()).get(0).intValue());
+//        }
+//    }
+//
+//    @Test
+//    @SuppressWarnings("unchecked")
+//    public void shouldLoadInitScript() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()){
+//            assertEquals(2, ((List<Integer>) client.submit("addItUp(1,1)").get(0).getResult().getData()).get(0).intValue());
+//        }
+//    }
+//
+//    @Test
+//    public void shouldGarbageCollectPhantomButNotHard() throws Exception {
+//        final Cluster cluster = Cluster.open();
+//        final Client client = cluster.connect();
+//
+//        assertEquals(2, client.submit("addItUp(1,1)").all().join().get(0).getInt());
+//        assertEquals(0, client.submit("def subtract(x,y){x-y};subtract(1,1)").all().join().get(0).getInt());
+//        assertEquals(0, client.submit("subtract(1,1)").all().join().get(0).getInt());
+//
+//        final Map<String, Object> bindings = new HashMap<>();
+//        bindings.put(GremlinGroovyScriptEngine.KEY_REFERENCE_TYPE, GremlinGroovyScriptEngine.REFERENCE_TYPE_PHANTOM);
+//        assertEquals(4, client.submit("def multiply(x,y){x*y};multiply(2,2)", bindings).all().join().get(0).getInt());
+//
+//        try {
+//            client.submit("multiply(2,2)").all().join().get(0).getInt();
+//            fail("Should throw an exception since reference is phantom.");
+//        } catch (RuntimeException ignored) {
+//
+//        } finally {
+//            cluster.close();
+//        }
+//    }
+//
+//    @Test
+//    public void shouldReceiveFailureOnBadGraphSONSerialization() throws Exception {
+//        final Cluster cluster = Cluster.build("localhost").serializer(Serializers.GRAPHSON_V1D0).create();
+//        final Client client = cluster.connect();
+//
+//        try {
+//            client.submit("def class C { def C getC(){return this}}; new C()").all().join();
+//            fail("Should throw an exception.");
+//        } catch (RuntimeException re) {
+//            final Throwable root = ExceptionUtils.getRootCause(re);
+//            assertThat(root.getMessage(), CoreMatchers.startsWith("Error during serialization: Direct self-reference leading to cycle (through reference chain:"));
+//
+//            // validate that we can still send messages to the server
+//            assertEquals(2, client.submit("1+1").all().join().get(0).getInt());
+//        } finally {
+//            cluster.close();
+//        }
+//    }
+//
+//    @Test
+//    public void shouldReceiveFailureOnBadGryoSerialization() throws Exception {
+//        final Cluster cluster = Cluster.build("localhost").serializer(Serializers.GRYO_V1D0).create();
+//        final Client client = cluster.connect();
+//
+//        try {
+//            client.submit("java.awt.Color.RED").all().join();
+//            fail("Should throw an exception.");
+//        } catch (RuntimeException re) {
+//            final Throwable root = ExceptionUtils.getRootCause(re);
+//            assertThat(root.getMessage(), CoreMatchers.startsWith("Error during serialization: Class is not registered: java.awt.Color"));
+//
+//            // validate that we can still send messages to the server
+//            assertEquals(2, client.submit("1+1").all().join().get(0).getInt());
+//        } finally {
+//            cluster.close();
+//        }
+//    }
+//
+//    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+//    @Test
+//    public void shouldBlockRequestWhenTooBig() throws Exception {
+//        final Cluster cluster = Cluster.open();
+//        final Client client = cluster.connect();
+//
+//        try {
+//            final String fatty = IntStream.range(0, 1024).mapToObj(String::valueOf).collect(Collectors.joining());
+//            final CompletableFuture<ResultSet> result = client.submitAsync("'" + fatty + "';'test'");
+//            final ResultSet resultSet = result.get(10000, TimeUnit.MILLISECONDS);
+//            resultSet.all().get(10000, TimeUnit.MILLISECONDS);
+//            fail("Should throw an exception.");
+//        } catch (TimeoutException te) {
+//            // the request should not have timed-out - the connection should have been reset, but it seems that
+//            // timeout seems to occur as well on some systems (it's not clear why).  however, the nature of this
+//            // test is to ensure that the script isn't processed if it exceeds a certain size, so in this sense
+//            // it seems ok to pass in this case.
+//        } catch (Exception re) {
+//            final Throwable root = ExceptionUtils.getRootCause(re);
+//            assertEquals("Connection reset by peer", root.getMessage());
+//
+//            // validate that we can still send messages to the server
+//            assertEquals(2, client.submit("1+1").all().join().get(0).getInt());
+//        } finally {
+//            cluster.close();
+//        }
+//    }
+//
+//    @Test
+//    public void shouldFailOnDeadHost() throws Exception {
+//        final Cluster cluster = Cluster.build("localhost").create();
+//        final Client client = cluster.connect();
+//
+//        // ensure that connection to server is good
+//        assertEquals(2, client.submit("1+1").all().join().get(0).getInt());
+//
+//        // kill the server which will make the client mark the host as unavailable
+//        this.stopServer();
+//
+//        try {
+//            // try to re-issue a request now that the server is down
+//            client.submit("1+1").all().join();
+//            fail();
+//        } catch (RuntimeException re) {
+//            assertTrue(re.getCause().getCause() instanceof ClosedChannelException);
+//
+//            //
+//            // should recover when the server comes back
+//            //
+//
+//            // restart server
+//            this.startServer();
+//            // the retry interval is 1 second, wait a bit longer
+//            TimeUnit.SECONDS.sleep(5);
+//
+//            List<Result> results = client.submit("1+1").all().join();
+//            assertEquals(1, results.size());
+//            assertEquals(2, results.get(0).getInt());
+//
+//        } finally {
+//            cluster.close();
+//        }
+//    }
+//
+//    @Test
+//    public void shouldNotHavePartialContentWithOneResult() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()) {
+//            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+//                    .addArg(Tokens.ARGS_GREMLIN, "10").create();
+//            final List<ResponseMessage> responses = client.submit(request);
+//            assertEquals(1, responses.size());
+//            assertEquals(ResponseStatusCode.SUCCESS, responses.get(0).getStatus().getCode());
+//        }
+//    }
+//
+//    @Test
+//    public void shouldFailWithBadScriptEval() throws Exception {
+//        try (SimpleClient client = new WebSocketClient()) {
+//            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+//                    .addArg(Tokens.ARGS_GREMLIN, "new String().doNothingAtAllBecauseThis is a syntax error").create();
+//            final List<ResponseMessage> responses = client.submit(request);
+//            assertEquals(ResponseStatusCode.SERVER_ERROR_SCRIPT_EVALUATION, responses.get(0).getStatus().getCode());
+//            assertEquals(1, responses.size());
+//        }
+//    }
+//
+//    @Test
+//    @SuppressWarnings("unchecked")
+//    public void shouldStillSupportDeprecatedRebindingsParameterOnServer() throws Exception {
+//        // this test can be removed when the rebindings arg is removed
+//        try (SimpleClient client = new WebSocketClient()) {
+//            final Map<String,String> rebindings = new HashMap<>();
+//            rebindings.put("xyz", "graph");
+//            final RequestMessage request = RequestMessage.build(Tokens.OPS_EVAL)
+//                    .addArg(Tokens.ARGS_GREMLIN, "xyz.addVertex('name','jason')")
+//                    .addArg(Tokens.ARGS_REBINDINGS, rebindings).create();
+//            final List<ResponseMessage> responses = client.submit(request);
+//            assertEquals(1, responses.size());
+//
+//            final DetachedVertex v = ((ArrayList<DetachedVertex>) responses.get(0).getResult().getData()).get(0);
+//            assertEquals("jason", v.value("name"));
+//        }
+//    }
 }


[4/6] incubator-tinkerpop git commit: Added additional SSL configuration options for Gremlin Driver.

Posted by sp...@apache.org.
Added additional SSL configuration options for Gremlin Driver.

Specifically added: keyPassword, keyFile and keyCertChainFile.


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

Branch: refs/heads/TINKERPOP-1269
Commit: 57416163be0470d0dcd124bebc12efe325578805
Parents: ec730eb
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Tue Apr 19 13:53:35 2016 -0400
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Wed Apr 20 15:07:15 2016 -0400

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../tinkerpop/gremlin/driver/Channelizer.java   | 38 +++++++++++++++-----
 .../tinkerpop/gremlin/driver/Cluster.java       | 33 +++++++++++++++++
 .../tinkerpop/gremlin/driver/Settings.java      | 15 ++++++++
 4 files changed, 78 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/57416163/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 9e117e1..32b534d 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/incubator-tinkerpop/master/docs/
 TinkerPop 3.1.3 (NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Added driver configuration settings for SSL: `keyCertChainFile`, `keyFile` and `keyPassword`.
 * Fixed bug where transaction managed sessions were not properly rolling back transactions for exceptions encountered during script evaluation.
 * Fixed bug in `:uninstall` command if the default `/ext` directory was not used.
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/57416163/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
index b059c3f..c850a11 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Channelizer.java
@@ -21,7 +21,9 @@ package org.apache.tinkerpop.gremlin.driver;
 import io.netty.channel.Channel;
 import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
 import io.netty.handler.ssl.SslContextBuilder;
+import io.netty.handler.ssl.SslProvider;
 import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
+import io.netty.handler.ssl.util.SelfSignedCertificate;
 import org.apache.tinkerpop.gremlin.driver.exception.ConnectionException;
 import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinRequestEncoder;
 import org.apache.tinkerpop.gremlin.driver.handler.NioGremlinResponseDecoder;
@@ -41,7 +43,9 @@ import io.netty.handler.ssl.SslContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.net.ssl.SSLException;
 import java.io.File;
+import java.security.cert.CertificateException;
 import java.util.Optional;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentMap;
@@ -116,15 +120,7 @@ public interface Channelizer extends ChannelHandler {
             final Optional<SslContext> sslCtx;
             if (supportsSsl()) {
                 try {
-                    final SslContextBuilder builder = SslContextBuilder.forClient();
-                    if (cluster.connectionPoolSettings().trustCertChainFile != null)
-                        builder.trustManager(new File(cluster.connectionPoolSettings().trustCertChainFile));
-                    else {
-                        logger.warn("SSL configured without a trustCertChainFile and thus trusts all certificates without verification (not suitable for production)");
-                        builder.trustManager(InsecureTrustManagerFactory.INSTANCE);
-                    }
-
-                    sslCtx = Optional.of(builder.build());
+                    sslCtx = Optional.of(createSSLContext(cluster.connectionPoolSettings()));
                 } catch (Exception ex) {
                     throw new RuntimeException(ex);
                 }
@@ -140,6 +136,30 @@ public interface Channelizer extends ChannelHandler {
             pipeline.addLast(PIPELINE_GREMLIN_SASL_HANDLER, new Handler.GremlinSaslAuthenticationHandler(cluster.authProperties()));
             pipeline.addLast(PIPELINE_GREMLIN_HANDLER, new Handler.GremlinResponseHandler(pending));
         }
+
+        private SslContext createSSLContext(final Settings.ConnectionPoolSettings sslSettings) throws Exception  {
+            final SslProvider provider = SslProvider.JDK;
+
+            final SslContextBuilder builder = SslContextBuilder.forClient();
+            if (cluster.connectionPoolSettings().trustCertChainFile != null)
+                builder.trustManager(new File(cluster.connectionPoolSettings().trustCertChainFile));
+            else {
+                logger.warn("SSL configured without a trustCertChainFile and thus trusts all certificates without verification (not suitable for production)");
+                builder.trustManager(InsecureTrustManagerFactory.INSTANCE);
+            }
+
+            if (null != sslSettings.keyCertChainFile && null != sslSettings.keyFile) {
+                final File keyCertChainFile = new File(sslSettings.keyCertChainFile);
+                final File keyFile = new File(sslSettings.keyFile);
+
+                // note that keyPassword may be null here if the keyFile is not password-protected.
+                builder.keyManager(keyCertChainFile, keyFile, sslSettings.keyPassword);
+            }
+
+            builder.sslProvider(provider);
+
+            return builder.build();
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/57416163/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
index 02181e2..7ae898b 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Cluster.java
@@ -144,6 +144,9 @@ public final class Cluster {
                 .port(settings.port)
                 .enableSsl(settings.connectionPool.enableSsl)
                 .trustCertificateChainFile(settings.connectionPool.trustCertChainFile)
+                .keyCertChainFile(settings.connectionPool.keyCertChainFile)
+                .keyFile(settings.connectionPool.keyFile)
+                .keyPassword(settings.connectionPool.keyPassword)
                 .nioPoolSize(settings.nioPoolSize)
                 .workerPoolSize(settings.workerPoolSize)
                 .reconnectInterval(settings.connectionPool.reconnectInterval)
@@ -286,6 +289,9 @@ public final class Cluster {
         private String channelizer = Channelizer.WebSocketChannelizer.class.getName();
         private boolean enableSsl = false;
         private String trustCertChainFile = null;
+        private String keyCertChainFile = null;
+        private String keyFile = null;
+        private String keyPassword = null;
         private LoadBalancingStrategy loadBalancingStrategy = new LoadBalancingStrategy.RoundRobin();
         private AuthProperties authProps = new AuthProperties();
 
@@ -363,6 +369,30 @@ public final class Cluster {
         }
 
         /**
+         * The X.509 certificate chain file in PEM format.
+         */
+        public Builder keyCertChainFile(final String keyCertChainFile) {
+            this.keyCertChainFile = keyCertChainFile;
+            return this;
+        }
+
+        /**
+         * The PKCS#8 private key file in PEM format.
+         */
+        public Builder keyFile(final String keyFile) {
+            this.keyFile = keyFile;
+            return this;
+        }
+
+        /**
+         * The password of the {@link #keyFile}, or {@code null} if it's not password-protected.
+         */
+        public Builder keyPassword(final String keyPassword) {
+            this.keyPassword = keyPassword;
+            return this;
+        }
+
+        /**
          * The minimum number of in-flight requests that can occur on a {@link Connection} before it is considered
          * for closing on return to the {@link ConnectionPool}.
          */
@@ -587,6 +617,9 @@ public final class Cluster {
             connectionPoolSettings.resultIterationBatchSize = this.resultIterationBatchSize;
             connectionPoolSettings.enableSsl = this.enableSsl;
             connectionPoolSettings.trustCertChainFile = this.trustCertChainFile;
+            connectionPoolSettings.keyCertChainFile = this.keyCertChainFile;
+            connectionPoolSettings.keyFile = this.keyFile;
+            connectionPoolSettings.keyPassword = this.keyPassword;
             connectionPoolSettings.channelizer = this.channelizer;
             return new Cluster(getContactPoints(), serializer, this.nioPoolSize, this.workerPoolSize,
                     connectionPoolSettings, loadBalancingStrategy, authProps);

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/57416163/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Settings.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Settings.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Settings.java
index 4daa223..373b9c7 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Settings.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/Settings.java
@@ -119,6 +119,21 @@ final class Settings {
         public String trustCertChainFile = null;
 
         /**
+         * The X.509 certificate chain file in PEM format.
+         */
+        public String keyCertChainFile = null;
+
+        /**
+         * The PKCS#8 private key file in PEM format.
+         */
+        public String keyFile = null;
+
+        /**
+         * The password of the {@link #keyFile}, or {@code null} if it's not password-protected.
+         */
+        public String keyPassword = null;
+
+        /**
          * The minimum size of a connection pool for a {@link Host}. By default this is set to 2.
          */
         public int minSize = ConnectionPool.MIN_POOL_SIZE;