diff --git a/community/bolt/src/main/java/org/neo4j/bolt/BoltServer.java b/community/bolt/src/main/java/org/neo4j/bolt/BoltServer.java
index a42dbe761f35f..4fed2e51cb26d 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/BoltServer.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/BoltServer.java
@@ -41,8 +41,8 @@
import org.neo4j.bolt.transport.NettyServer.ProtocolInitializer;
import org.neo4j.bolt.transport.SocketTransport;
import org.neo4j.bolt.transport.TransportThrottleGroup;
-import org.neo4j.bolt.v1.runtime.BoltStateMachineFactory;
-import org.neo4j.bolt.v1.runtime.BoltStateMachineFactoryImpl;
+import org.neo4j.bolt.runtime.BoltStateMachineFactory;
+import org.neo4j.bolt.runtime.BoltStateMachineFactoryImpl;
import org.neo4j.graphdb.DependencyResolver;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.helpers.ListenSocketAddress;
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLogger.java b/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLogger.java
index 0d715071b2ad4..601a580ff9773 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLogger.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLogger.java
@@ -40,7 +40,7 @@ public interface BoltMessageLogger
void serverError( String eventName, Status status );
- void logInit( String userAgent );
+ void logUserAgent( String userAgent );
void logRun();
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLoggerImpl.java b/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLoggerImpl.java
index 36759650ea3ba..fe35fe7e0caf5 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLoggerImpl.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/logging/BoltMessageLoggerImpl.java
@@ -102,7 +102,7 @@ public void serverError( String eventName, Status status )
}
@Override
- public void logInit( String userAgent )
+ public void logUserAgent( String userAgent )
{
clientEvent( "INIT", () -> userAgent);
}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/logging/NullBoltMessageLogger.java b/community/bolt/src/main/java/org/neo4j/bolt/logging/NullBoltMessageLogger.java
index 43512fc088a20..9e55a2199981e 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/logging/NullBoltMessageLogger.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/logging/NullBoltMessageLogger.java
@@ -73,7 +73,7 @@ public void serverError( String eventName, Status status )
}
@Override
- public void logInit( String userAgent )
+ public void logUserAgent( String userAgent )
{
}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/runtime/BoltStateMachine.java b/community/bolt/src/main/java/org/neo4j/bolt/runtime/BoltStateMachine.java
index 263195999208d..4127b808f9e5d 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/runtime/BoltStateMachine.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/runtime/BoltStateMachine.java
@@ -47,4 +47,6 @@ public interface BoltStateMachine extends ManagedBoltStateMachine, AutoCloseable
@Override
void close();
+
+ String id();
}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineFactory.java b/community/bolt/src/main/java/org/neo4j/bolt/runtime/BoltStateMachineFactory.java
similarity index 93%
rename from community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineFactory.java
rename to community/bolt/src/main/java/org/neo4j/bolt/runtime/BoltStateMachineFactory.java
index ab149071b1e94..becb84efb9a85 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineFactory.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/runtime/BoltStateMachineFactory.java
@@ -17,10 +17,9 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package org.neo4j.bolt.v1.runtime;
+package org.neo4j.bolt.runtime;
import org.neo4j.bolt.BoltChannel;
-import org.neo4j.bolt.runtime.BoltStateMachine;
/**
* Factory class for Bolt runtime environments.
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineFactoryImpl.java b/community/bolt/src/main/java/org/neo4j/bolt/runtime/BoltStateMachineFactoryImpl.java
similarity index 74%
rename from community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineFactoryImpl.java
rename to community/bolt/src/main/java/org/neo4j/bolt/runtime/BoltStateMachineFactoryImpl.java
index c2ae72ac535bc..d094159b5f459 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineFactoryImpl.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/runtime/BoltStateMachineFactoryImpl.java
@@ -17,16 +17,19 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-package org.neo4j.bolt.v1.runtime;
+package org.neo4j.bolt.runtime;
import java.time.Clock;
import java.time.Duration;
import org.neo4j.bolt.BoltChannel;
-import org.neo4j.bolt.runtime.BoltStateMachine;
-import org.neo4j.bolt.runtime.BoltStateMachineSPI;
-import org.neo4j.bolt.runtime.TransactionStateMachineSPI;
import org.neo4j.bolt.security.auth.Authentication;
+import org.neo4j.bolt.v1.BoltProtocolV1;
+import org.neo4j.bolt.v1.runtime.BoltStateMachineV1;
+import org.neo4j.bolt.v1.runtime.BoltStateMachineV1SPI;
+import org.neo4j.bolt.v2.BoltProtocolV2;
+import org.neo4j.bolt.v3.BoltProtocolV3;
+import org.neo4j.bolt.v3.BoltStateMachineV3;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.kernel.AvailabilityGuard;
import org.neo4j.kernel.api.bolt.BoltConnectionTracker;
@@ -62,7 +65,18 @@ public BoltStateMachineFactoryImpl( GraphDatabaseAPI db, UsageData usageData, Av
@Override
public BoltStateMachine newStateMachine( long protocolVersion, BoltChannel boltChannel )
{
- return newStateMachineV1( boltChannel );
+ if ( protocolVersion == BoltProtocolV1.VERSION || protocolVersion == BoltProtocolV2.VERSION )
+ {
+ return newStateMachineV1( boltChannel );
+ }
+ else if ( protocolVersion == BoltProtocolV3.VERSION )
+ {
+ return newStateMachineV3( boltChannel );
+ }
+ else
+ {
+ return null;
+ }
}
private BoltStateMachine newStateMachineV1( BoltChannel boltChannel )
@@ -72,6 +86,13 @@ private BoltStateMachine newStateMachineV1( BoltChannel boltChannel )
return new BoltStateMachineV1( boltSPI, boltChannel, clock );
}
+ private BoltStateMachine newStateMachineV3( BoltChannel boltChannel )
+ {
+ TransactionStateMachineSPI transactionSPI = createTxSpi( clock );
+ BoltStateMachineSPI boltSPI = new BoltStateMachineV1SPI( boltChannel, usageData, logging, authentication, connectionTracker, transactionSPI );
+ return new BoltStateMachineV3( boltSPI, boltChannel, clock );
+ }
+
private TransactionStateMachineSPI createTxSpi( Clock clock )
{
long bookmarkReadyTimeout = config.get( GraphDatabaseSettings.bookmark_ready_timeout ).toMillis();
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/runtime/DefaultBoltConnectionFactory.java b/community/bolt/src/main/java/org/neo4j/bolt/runtime/DefaultBoltConnectionFactory.java
index a629e6a2a1c76..7a1ac70047f57 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/runtime/DefaultBoltConnectionFactory.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/runtime/DefaultBoltConnectionFactory.java
@@ -27,6 +27,8 @@
import org.neo4j.kernel.impl.logging.LogService;
import org.neo4j.kernel.monitoring.Monitors;
+import static java.util.Objects.requireNonNull;
+
public class DefaultBoltConnectionFactory implements BoltConnectionFactory
{
private final BoltSchedulerProvider schedulerProvider;
@@ -52,6 +54,9 @@ public DefaultBoltConnectionFactory( BoltSchedulerProvider schedulerProvider, Tr
@Override
public BoltConnection newConnection( BoltChannel channel, BoltStateMachine stateMachine )
{
+ requireNonNull( channel );
+ requireNonNull( stateMachine );
+
BoltScheduler scheduler = schedulerProvider.get( channel );
BoltConnectionQueueMonitor connectionQueueMonitor =
queueMonitor == null ? scheduler : new BoltConnectionQueueMonitorAggregate( scheduler, queueMonitor );
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/runtime/StateMachineContext.java b/community/bolt/src/main/java/org/neo4j/bolt/runtime/StateMachineContext.java
index ed3dfee4bbe62..056b710dd37db 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/runtime/StateMachineContext.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/runtime/StateMachineContext.java
@@ -34,4 +34,6 @@ public interface StateMachineContext
MutableConnectionState connectionState();
Clock clock();
+
+ String connectionId();
}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/transport/DefaultBoltProtocolFactory.java b/community/bolt/src/main/java/org/neo4j/bolt/transport/DefaultBoltProtocolFactory.java
index f71ccf7367fed..6e37d34317092 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/transport/DefaultBoltProtocolFactory.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/transport/DefaultBoltProtocolFactory.java
@@ -19,12 +19,15 @@
*/
package org.neo4j.bolt.transport;
+import java.io.IOException;
+
import org.neo4j.bolt.BoltChannel;
import org.neo4j.bolt.BoltProtocol;
import org.neo4j.bolt.runtime.BoltConnectionFactory;
+import org.neo4j.bolt.runtime.BoltStateMachineFactory;
import org.neo4j.bolt.v1.BoltProtocolV1;
-import org.neo4j.bolt.v1.runtime.BoltStateMachineFactory;
import org.neo4j.bolt.v2.BoltProtocolV2;
+import org.neo4j.bolt.v3.BoltProtocolV3;
import org.neo4j.kernel.impl.logging.LogService;
public class DefaultBoltProtocolFactory implements BoltProtocolFactory
@@ -52,6 +55,10 @@ else if ( protocolVersion == BoltProtocolV2.VERSION )
{
return new BoltProtocolV2( channel, connectionFactory, stateMachineFactory, logService );
}
+ else if ( protocolVersion == BoltProtocolV3.VERSION )
+ {
+ return new BoltProtocolV3( channel, connectionFactory, stateMachineFactory, logService );
+ }
else
{
return null;
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/BoltProtocolV1.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/BoltProtocolV1.java
index e29b2865000d5..cdcda7fbae277 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v1/BoltProtocolV1.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/BoltProtocolV1.java
@@ -28,6 +28,7 @@
import org.neo4j.bolt.runtime.BoltConnection;
import org.neo4j.bolt.runtime.BoltConnectionFactory;
import org.neo4j.bolt.runtime.BoltStateMachine;
+import org.neo4j.bolt.runtime.BoltStateMachineFactory;
import org.neo4j.bolt.transport.pipeline.ChunkDecoder;
import org.neo4j.bolt.transport.pipeline.HouseKeeper;
import org.neo4j.bolt.transport.pipeline.MessageAccumulator;
@@ -35,7 +36,6 @@
import org.neo4j.bolt.v1.messaging.BoltRequestMessageReaderV1;
import org.neo4j.bolt.v1.messaging.BoltResponseMessageWriterV1;
import org.neo4j.bolt.v1.messaging.Neo4jPackV1;
-import org.neo4j.bolt.v1.runtime.BoltStateMachineFactory;
import org.neo4j.kernel.impl.logging.LogService;
/**
@@ -61,7 +61,7 @@ public BoltProtocolV1( BoltChannel channel, BoltConnectionFactory connectionFact
this.connection = connectionFactory.newConnection( channel, stateMachine );
this.neo4jPack = createPack();
- this.messageReader = createBoltMessageReaderV1( channel, neo4jPack, connection, logging );
+ this.messageReader = createMessageReader( channel, neo4jPack, connection, logging );
}
/**
@@ -89,7 +89,7 @@ public long version()
return VERSION;
}
- public static BoltRequestMessageReader createBoltMessageReaderV1( BoltChannel channel, Neo4jPack neo4jPack, BoltConnection connection, LogService logging )
+ protected BoltRequestMessageReader createMessageReader( BoltChannel channel, Neo4jPack neo4jPack, BoltConnection connection, LogService logging )
{
BoltResponseMessageWriterV1 responseWriter = new BoltResponseMessageWriterV1( neo4jPack, connection.output(), logging, channel.log() );
return new BoltRequestMessageReaderV1( connection, responseWriter, channel.log(), logging );
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/BoltStateMachineV1Context.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/BoltStateMachineV1Context.java
index b5dd2a6c9cb7b..6bc1476d92bfb 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/BoltStateMachineV1Context.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/BoltStateMachineV1Context.java
@@ -77,4 +77,10 @@ public Clock clock()
{
return clock;
}
+
+ @Override
+ public String connectionId()
+ {
+ return machine.id();
+ }
}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/MessageProcessingHandler.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/MessageProcessingHandler.java
index 41ef50265d35e..29fc6ca157e47 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/MessageProcessingHandler.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/MessageProcessingHandler.java
@@ -40,7 +40,7 @@
import static org.neo4j.bolt.v1.messaging.response.IgnoredMessage.IGNORED_MESSAGE;
-class MessageProcessingHandler implements BoltResponseHandler
+public class MessageProcessingHandler implements BoltResponseHandler
{
// Errors that are expected when the client disconnects mid-operation
private static final Set CLIENT_MID_OP_DISCONNECT_ERRORS =
@@ -54,7 +54,7 @@ class MessageProcessingHandler implements BoltResponseHandler
private Neo4jError error;
private boolean ignored;
- MessageProcessingHandler( BoltResponseMessageWriter messageWriter, BoltConnection connection, Log logger )
+ public MessageProcessingHandler( BoltResponseMessageWriter messageWriter, BoltConnection connection, Log logger )
{
this.messageWriter = messageWriter;
this.connection = connection;
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/ResultHandler.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/ResultHandler.java
index 5c4a7bed48336..fbb0ac3e8d826 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/ResultHandler.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/ResultHandler.java
@@ -27,9 +27,9 @@
import org.neo4j.logging.Log;
import org.neo4j.values.AnyValue;
-class ResultHandler extends MessageProcessingHandler
+public class ResultHandler extends MessageProcessingHandler
{
- ResultHandler( BoltResponseMessageWriter handler, BoltConnection connection, Log log )
+ public ResultHandler( BoltResponseMessageWriter handler, BoltConnection connection, Log log )
{
super( handler, connection, log );
}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/decoder/InitMessageDecoder.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/decoder/InitMessageDecoder.java
index 9d56a9ee78d7e..ff63247ed4b86 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/decoder/InitMessageDecoder.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/decoder/InitMessageDecoder.java
@@ -59,7 +59,7 @@ public RequestMessage decode( Neo4jPack.Unpacker unpacker ) throws IOException
{
String userAgent = unpacker.unpackString();
Map authToken = readAuthToken( unpacker );
- messageLogger.logInit( userAgent );
+ messageLogger.logUserAgent( userAgent );
return new InitMessage( userAgent, authToken );
}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/decoder/PrimitiveOnlyValueWriter.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/decoder/PrimitiveOnlyValueWriter.java
index 74ccd212767c7..64c5895af3a5a 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/decoder/PrimitiveOnlyValueWriter.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/messaging/decoder/PrimitiveOnlyValueWriter.java
@@ -37,9 +37,9 @@
* {@link AnyValueWriter Writer} that allows to convert {@link AnyValue} to any primitive Java type. It explicitly
* prohibits conversion of nodes, relationships, spatial and temporal types. They are not expected in auth token map.
*/
-class PrimitiveOnlyValueWriter extends BaseToObjectValueWriter
+public class PrimitiveOnlyValueWriter extends BaseToObjectValueWriter
{
- Object valueAsObject( AnyValue value )
+ public Object valueAsObject( AnyValue value )
{
value.writeTo( this );
return value();
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineV1.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineV1.java
index 4f2a26afc67af..e15ee43e2b697 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineV1.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineV1.java
@@ -233,6 +233,12 @@ public void close()
}
}
+ @Override
+ public String id()
+ {
+ return id;
+ }
+
@Override
public String owner()
{
@@ -351,7 +357,7 @@ private void resetStatementProcessor()
}
}
- private static States buildStates()
+ protected States buildStates()
{
ConnectedState connected = new ConnectedState();
ReadyState ready = new ReadyState();
@@ -379,12 +385,12 @@ private static States buildStates()
return new States( connected, failed );
}
- private static class States
+ public static class States
{
final BoltStateMachineState initial;
final BoltStateMachineState failed;
- States( BoltStateMachineState initial, BoltStateMachineState failed )
+ public States( BoltStateMachineState initial, BoltStateMachineState failed )
{
this.initial = initial;
this.failed = failed;
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineV1SPI.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineV1SPI.java
index 927f56a95a04c..fef706b350190 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineV1SPI.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/BoltStateMachineV1SPI.java
@@ -35,7 +35,7 @@
import org.neo4j.udc.UsageData;
import org.neo4j.udc.UsageDataKeys;
-class BoltStateMachineV1SPI implements BoltStateMachineSPI
+public class BoltStateMachineV1SPI implements BoltStateMachineSPI
{
private final BoltConnectionDescriptor connectionDescriptor;
private final UsageData usageData;
@@ -45,7 +45,7 @@ class BoltStateMachineV1SPI implements BoltStateMachineSPI
private final String version;
private final TransactionStateMachineSPI transactionSpi;
- BoltStateMachineV1SPI( BoltConnectionDescriptor connectionDescriptor, UsageData usageData, LogService logging, Authentication authentication,
+ public BoltStateMachineV1SPI( BoltConnectionDescriptor connectionDescriptor, UsageData usageData, LogService logging, Authentication authentication,
BoltConnectionTracker connectionTracker, TransactionStateMachineSPI transactionStateMachineSPI )
{
this.connectionDescriptor = connectionDescriptor;
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/TransactionStateMachineSPI.java b/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/TransactionStateMachineSPI.java
index a0aa57eecc03d..c14d7882f5bdc 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/TransactionStateMachineSPI.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v1/runtime/TransactionStateMachineSPI.java
@@ -52,7 +52,7 @@
import static java.lang.String.format;
import static org.neo4j.internal.kernel.api.Transaction.Type.implicit;
-class TransactionStateMachineSPI implements org.neo4j.bolt.runtime.TransactionStateMachineSPI
+public class TransactionStateMachineSPI implements org.neo4j.bolt.runtime.TransactionStateMachineSPI
{
private static final PropertyContainerLocker locker = new PropertyContainerLocker();
@@ -64,7 +64,7 @@ class TransactionStateMachineSPI implements org.neo4j.bolt.runtime.TransactionSt
private final Duration txAwaitDuration;
private final Clock clock;
- TransactionStateMachineSPI( GraphDatabaseAPI db, AvailabilityGuard availabilityGuard, Duration txAwaitDuration, Clock clock )
+ public TransactionStateMachineSPI( GraphDatabaseAPI db, AvailabilityGuard availabilityGuard, Duration txAwaitDuration, Clock clock )
{
this.db = db;
this.txBridge = db.getDependencyResolver().resolveDependency( ThreadToStatementContextBridge.class );
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v2/BoltProtocolV2.java b/community/bolt/src/main/java/org/neo4j/bolt/v2/BoltProtocolV2.java
index 47056d2b6e78b..3862723670f48 100644
--- a/community/bolt/src/main/java/org/neo4j/bolt/v2/BoltProtocolV2.java
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v2/BoltProtocolV2.java
@@ -22,8 +22,8 @@
import org.neo4j.bolt.BoltChannel;
import org.neo4j.bolt.messaging.Neo4jPack;
import org.neo4j.bolt.runtime.BoltConnectionFactory;
+import org.neo4j.bolt.runtime.BoltStateMachineFactory;
import org.neo4j.bolt.v1.BoltProtocolV1;
-import org.neo4j.bolt.v1.runtime.BoltStateMachineFactory;
import org.neo4j.bolt.v2.messaging.Neo4jPackV2;
import org.neo4j.kernel.impl.logging.LogService;
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v3/BoltProtocolV3.java b/community/bolt/src/main/java/org/neo4j/bolt/v3/BoltProtocolV3.java
new file mode 100644
index 0000000000000..489ad3ba20d4d
--- /dev/null
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v3/BoltProtocolV3.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3;
+
+import org.neo4j.bolt.BoltChannel;
+import org.neo4j.bolt.messaging.BoltRequestMessageReader;
+import org.neo4j.bolt.messaging.Neo4jPack;
+import org.neo4j.bolt.runtime.BoltConnection;
+import org.neo4j.bolt.runtime.BoltConnectionFactory;
+import org.neo4j.bolt.runtime.BoltStateMachineFactory;
+import org.neo4j.bolt.v1.BoltProtocolV1;
+import org.neo4j.bolt.v1.messaging.BoltResponseMessageWriterV1;
+import org.neo4j.bolt.v2.messaging.Neo4jPackV2;
+import org.neo4j.bolt.v3.messaging.BoltRequestMessageReaderV3;
+import org.neo4j.kernel.impl.logging.LogService;
+
+/**
+ * Bolt protocol V3. It hosts all the components that are specific to BoltV3
+ */
+public class BoltProtocolV3 extends BoltProtocolV1
+{
+ public static final long VERSION = 3;
+
+ public BoltProtocolV3( BoltChannel channel, BoltConnectionFactory connectionFactory, BoltStateMachineFactory stateMachineFactory, LogService logging )
+ {
+ super( channel, connectionFactory, stateMachineFactory, logging );
+ }
+
+ protected Neo4jPack createPack()
+ {
+ return new Neo4jPackV2();
+ }
+
+ @Override
+ public long version()
+ {
+ return VERSION;
+ }
+
+ protected BoltRequestMessageReader createMessageReader( BoltChannel channel, Neo4jPack neo4jPack, BoltConnection connection, LogService logging )
+ {
+ BoltResponseMessageWriterV1 responseWriter = new BoltResponseMessageWriterV1( neo4jPack, connection.output(), logging, channel.log() );
+ return new BoltRequestMessageReaderV3( connection, responseWriter, channel.log(), logging );
+ }
+}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v3/BoltStateMachineV3.java b/community/bolt/src/main/java/org/neo4j/bolt/v3/BoltStateMachineV3.java
new file mode 100644
index 0000000000000..eefb7a79c3fb3
--- /dev/null
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v3/BoltStateMachineV3.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3;
+
+import java.time.Clock;
+
+import org.neo4j.bolt.BoltChannel;
+import org.neo4j.bolt.runtime.BoltStateMachineSPI;
+import org.neo4j.bolt.v1.runtime.BoltStateMachineV1;
+import org.neo4j.bolt.v1.runtime.ConnectedState;
+import org.neo4j.bolt.v1.runtime.FailedState;
+import org.neo4j.bolt.v1.runtime.InterruptedState;
+import org.neo4j.bolt.v1.runtime.ReadyState;
+import org.neo4j.bolt.v1.runtime.StreamingState;
+import org.neo4j.bolt.v3.runtime.ExtraMetaDataConnectedState;
+
+public class BoltStateMachineV3 extends BoltStateMachineV1
+{
+ public BoltStateMachineV3( BoltStateMachineSPI boltSPI, BoltChannel boltChannel, Clock clock )
+ {
+ super( boltSPI, boltChannel, clock );
+ }
+
+ @Override
+ protected States buildStates()
+ {
+ ConnectedState connected = new ExtraMetaDataConnectedState();
+ ReadyState ready = new ReadyState();
+ StreamingState streaming = new StreamingState();
+ FailedState failed = new FailedState();
+ InterruptedState interrupted = new InterruptedState();
+
+ connected.setReadyState( ready );
+ connected.setFailedState( failed );
+
+ ready.setStreamingState( streaming );
+ ready.setInterruptedState( interrupted );
+ ready.setFailedState( failed );
+
+ streaming.setReadyState( ready );
+ streaming.setInterruptedState( interrupted );
+ streaming.setFailedState( failed );
+
+ failed.setReadyState( ready );
+ failed.setInterruptedState( interrupted );
+
+ interrupted.setReadyState( ready );
+ interrupted.setFailedState( failed );
+
+ return new States( connected, failed );
+ }
+}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v3/messaging/BoltRequestMessageReaderV3.java b/community/bolt/src/main/java/org/neo4j/bolt/v3/messaging/BoltRequestMessageReaderV3.java
new file mode 100644
index 0000000000000..7456bdbd7463d
--- /dev/null
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v3/messaging/BoltRequestMessageReaderV3.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3.messaging;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.neo4j.bolt.logging.BoltMessageLogger;
+import org.neo4j.bolt.messaging.BoltRequestMessageReader;
+import org.neo4j.bolt.messaging.BoltResponseMessageWriter;
+import org.neo4j.bolt.messaging.RequestMessageDecoder;
+import org.neo4j.bolt.runtime.BoltConnection;
+import org.neo4j.bolt.runtime.BoltResponseHandler;
+import org.neo4j.bolt.v1.messaging.MessageProcessingHandler;
+import org.neo4j.bolt.v1.messaging.ResultHandler;
+import org.neo4j.bolt.v1.messaging.decoder.AckFailureMessageDecoder;
+import org.neo4j.bolt.v1.messaging.decoder.DiscardAllMessageDecoder;
+import org.neo4j.bolt.v1.messaging.decoder.PullAllMessageDecoder;
+import org.neo4j.bolt.v1.messaging.decoder.ResetMessageDecoder;
+import org.neo4j.bolt.v1.messaging.decoder.RunMessageDecoder;
+import org.neo4j.kernel.impl.logging.LogService;
+import org.neo4j.logging.Log;
+
+public class BoltRequestMessageReaderV3 extends BoltRequestMessageReader
+{
+ public BoltRequestMessageReaderV3( BoltConnection connection, BoltResponseMessageWriter responseMessageWriter,
+ BoltMessageLogger messageLogger, LogService logService )
+ {
+ super( connection,
+ newSimpleResponseHandler( connection, responseMessageWriter, logService ),
+ buildDecoders( connection, responseMessageWriter, messageLogger, logService ),
+ messageLogger );
+ }
+
+ private static List buildDecoders( BoltConnection connection, BoltResponseMessageWriter responseMessageWriter,
+ BoltMessageLogger messageLogger, LogService logService )
+ {
+ BoltResponseHandler helloHandler = newSimpleResponseHandler( connection, responseMessageWriter, logService );
+ BoltResponseHandler runHandler = newSimpleResponseHandler( connection, responseMessageWriter, logService );
+ BoltResponseHandler resultHandler = new ResultHandler( responseMessageWriter, connection, internalLog( logService ) );
+ BoltResponseHandler defaultHandler = newSimpleResponseHandler( connection, responseMessageWriter, logService );
+
+ return Arrays.asList(
+ new HelloMessageDecoder( helloHandler, messageLogger ),
+ new AckFailureMessageDecoder( defaultHandler, messageLogger ),
+ new ResetMessageDecoder( connection, defaultHandler, messageLogger ),
+ new RunMessageDecoder( runHandler, messageLogger ),
+ new DiscardAllMessageDecoder( resultHandler, messageLogger ),
+ new PullAllMessageDecoder( resultHandler, messageLogger )
+ );
+ }
+
+ private static BoltResponseHandler newSimpleResponseHandler( BoltConnection connection,
+ BoltResponseMessageWriter responseMessageWriter, LogService logService )
+ {
+ return new MessageProcessingHandler( responseMessageWriter, connection, internalLog( logService ) );
+ }
+
+ private static Log internalLog( LogService logService )
+ {
+ return logService.getInternalLog( BoltRequestMessageReaderV3.class );
+ }
+}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v3/messaging/HelloMessage.java b/community/bolt/src/main/java/org/neo4j/bolt/v3/messaging/HelloMessage.java
new file mode 100644
index 0000000000000..135aeb1944b9b
--- /dev/null
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v3/messaging/HelloMessage.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3.messaging;
+
+import java.util.Map;
+import java.util.Objects;
+
+import org.neo4j.bolt.v1.messaging.request.InitMessage;
+
+public class HelloMessage extends InitMessage
+{
+ public static final byte SIGNATURE = InitMessage.SIGNATURE;
+ private static final String USER_AGENT = "user_agent";
+ private final Map meta;
+
+ public HelloMessage( Map meta )
+ {
+ super( (String) meta.get( USER_AGENT ), meta );
+ this.meta = meta;
+ }
+
+ @Override
+ public boolean equals( Object o )
+ {
+ if ( this == o )
+ {
+ return true;
+ }
+ if ( o == null || getClass() != o.getClass() )
+ {
+ return false;
+ }
+ HelloMessage that = (HelloMessage) o;
+ return Objects.equals( meta, that.meta );
+ }
+
+ public Map meta()
+ {
+ return meta;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash( meta );
+ }
+
+ @Override
+ public String toString()
+ {
+ return "HELLO " + meta;
+ }
+}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v3/messaging/HelloMessageDecoder.java b/community/bolt/src/main/java/org/neo4j/bolt/v3/messaging/HelloMessageDecoder.java
new file mode 100644
index 0000000000000..8b51e5a100ca6
--- /dev/null
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v3/messaging/HelloMessageDecoder.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3.messaging;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.neo4j.bolt.logging.BoltMessageLogger;
+import org.neo4j.bolt.messaging.Neo4jPack;
+import org.neo4j.bolt.messaging.RequestMessage;
+import org.neo4j.bolt.messaging.RequestMessageDecoder;
+import org.neo4j.bolt.runtime.BoltResponseHandler;
+import org.neo4j.bolt.v1.messaging.decoder.PrimitiveOnlyValueWriter;
+import org.neo4j.values.virtual.MapValue;
+
+public class HelloMessageDecoder implements RequestMessageDecoder
+{
+ private final BoltResponseHandler responseHandler;
+ private final BoltMessageLogger messageLogger;
+
+ public HelloMessageDecoder( BoltResponseHandler responseHandler, BoltMessageLogger messageLogger )
+ {
+ this.responseHandler = responseHandler;
+ this.messageLogger = messageLogger;
+ }
+
+ @Override
+ public int signature()
+ {
+ return HelloMessage.SIGNATURE;
+ }
+
+ @Override
+ public BoltResponseHandler responseHandler()
+ {
+ return responseHandler;
+ }
+
+ @Override
+ public RequestMessage decode( Neo4jPack.Unpacker unpacker ) throws IOException
+ {
+ MapValue helloMeta = unpacker.unpackMap();
+ PrimitiveOnlyValueWriter writer = new PrimitiveOnlyValueWriter();
+ Map meta = new HashMap<>( helloMeta.size() );
+ helloMeta.foreach( ( key, value ) -> meta.put( key, writer.valueAsObject( value ) ) );
+ HelloMessage helloMessage = new HelloMessage( meta );
+
+ messageLogger.logUserAgent( helloMessage.userAgent() );
+ return helloMessage;
+ }
+}
diff --git a/community/bolt/src/main/java/org/neo4j/bolt/v3/runtime/ExtraMetaDataConnectedState.java b/community/bolt/src/main/java/org/neo4j/bolt/v3/runtime/ExtraMetaDataConnectedState.java
new file mode 100644
index 0000000000000..2f04ee84af3e4
--- /dev/null
+++ b/community/bolt/src/main/java/org/neo4j/bolt/v3/runtime/ExtraMetaDataConnectedState.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3.runtime;
+
+import org.neo4j.bolt.messaging.RequestMessage;
+import org.neo4j.bolt.runtime.BoltConnectionFatality;
+import org.neo4j.bolt.runtime.BoltStateMachineState;
+import org.neo4j.bolt.runtime.StateMachineContext;
+import org.neo4j.bolt.v1.runtime.ConnectedState;
+import org.neo4j.values.storable.Values;
+
+/**
+ * Following the socket connection and a small handshake exchange to
+ * establish protocol version, the machine begins in the CONNECTED
+ * state. The only valid transition from here is through a
+ * correctly authorised HELLO into the READY state. Any other action
+ * results in disconnection.
+ */
+public class ExtraMetaDataConnectedState extends ConnectedState
+{
+ private static final String ROUTING_TABLE_VALUE = "dbms.cluster.routing.getRoutingTable";
+ private static final String ROUTING_TABLE_KEY = "routing_table";
+ private static final String CONNECTION_ID_KEY = "connection_id";
+
+ @Override
+ public BoltStateMachineState process( RequestMessage message, StateMachineContext context ) throws BoltConnectionFatality
+ {
+ BoltStateMachineState processResult = super.process( message, context );
+ context.connectionState().onMetadata( ROUTING_TABLE_KEY, Values.stringValue( ROUTING_TABLE_VALUE ) );
+ context.connectionState().onMetadata( CONNECTION_ID_KEY, Values.stringValue( context.connectionId() ) );
+ return processResult;
+ }
+}
diff --git a/community/bolt/src/test/java/org/neo4j/bolt/logging/BoltMessageLoggerImplTest.java b/community/bolt/src/test/java/org/neo4j/bolt/logging/BoltMessageLoggerImplTest.java
index cc3a7c6539da0..cf01f79c7194e 100644
--- a/community/bolt/src/test/java/org/neo4j/bolt/logging/BoltMessageLoggerImplTest.java
+++ b/community/bolt/src/test/java/org/neo4j/bolt/logging/BoltMessageLoggerImplTest.java
@@ -124,7 +124,7 @@ public void logAckFailure()
public void logInit()
{
// when
- boltMessageLogger.logInit( "userAgent" );
+ boltMessageLogger.logUserAgent( "userAgent" );
// then
verify( boltMessageLog ).info( REMOTE_ADDRESS, CORRELATION_ID, "C INIT userAgent" );
diff --git a/community/bolt/src/test/java/org/neo4j/bolt/transport/DefaultBoltProtocolFactoryTest.java b/community/bolt/src/test/java/org/neo4j/bolt/transport/DefaultBoltProtocolFactoryTest.java
index 6ee9b2a95f1b8..752d891477bf5 100644
--- a/community/bolt/src/test/java/org/neo4j/bolt/transport/DefaultBoltProtocolFactoryTest.java
+++ b/community/bolt/src/test/java/org/neo4j/bolt/transport/DefaultBoltProtocolFactoryTest.java
@@ -31,7 +31,7 @@
import org.neo4j.bolt.runtime.BoltConnectionFactory;
import org.neo4j.bolt.runtime.BoltStateMachine;
import org.neo4j.bolt.v1.BoltProtocolV1;
-import org.neo4j.bolt.v1.runtime.BoltStateMachineFactory;
+import org.neo4j.bolt.runtime.BoltStateMachineFactory;
import org.neo4j.bolt.v2.BoltProtocolV2;
import org.neo4j.kernel.impl.logging.NullLogService;
diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v1/BoltProtocolV1Test.java b/community/bolt/src/test/java/org/neo4j/bolt/v1/BoltProtocolV1Test.java
index d28dc9f11648b..a86e66f5f9ddd 100644
--- a/community/bolt/src/test/java/org/neo4j/bolt/v1/BoltProtocolV1Test.java
+++ b/community/bolt/src/test/java/org/neo4j/bolt/v1/BoltProtocolV1Test.java
@@ -37,7 +37,7 @@
import org.neo4j.bolt.transport.pipeline.HouseKeeper;
import org.neo4j.bolt.transport.pipeline.MessageAccumulator;
import org.neo4j.bolt.transport.pipeline.MessageDecoder;
-import org.neo4j.bolt.v1.runtime.BoltStateMachineFactory;
+import org.neo4j.bolt.runtime.BoltStateMachineFactory;
import org.neo4j.kernel.impl.logging.NullLogService;
import static org.hamcrest.Matchers.instanceOf;
diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v1/messaging/BoltRequestMessageWriter.java b/community/bolt/src/test/java/org/neo4j/bolt/v1/messaging/BoltRequestMessageWriter.java
index 90cdb7697e9bf..a6b322ed7ef8e 100644
--- a/community/bolt/src/test/java/org/neo4j/bolt/v1/messaging/BoltRequestMessageWriter.java
+++ b/community/bolt/src/test/java/org/neo4j/bolt/v1/messaging/BoltRequestMessageWriter.java
@@ -34,7 +34,7 @@
public class BoltRequestMessageWriter
{
- private final Neo4jPack.Packer packer;
+ protected final Neo4jPack.Packer packer;
public BoltRequestMessageWriter( Neo4jPack.Packer packer )
{
diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/BoltStateMachineFactoryImplTest.java b/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/BoltStateMachineFactoryImplTest.java
index bda26354eda45..341a0ca722f1e 100644
--- a/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/BoltStateMachineFactoryImplTest.java
+++ b/community/bolt/src/test/java/org/neo4j/bolt/v1/runtime/BoltStateMachineFactoryImplTest.java
@@ -19,6 +19,7 @@
*/
package org.neo4j.bolt.v1.runtime;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
@@ -26,9 +27,11 @@
import org.neo4j.bolt.BoltChannel;
import org.neo4j.bolt.runtime.BoltStateMachine;
+import org.neo4j.bolt.runtime.BoltStateMachineFactoryImpl;
import org.neo4j.bolt.security.auth.Authentication;
import org.neo4j.bolt.v1.BoltProtocolV1;
import org.neo4j.bolt.v2.BoltProtocolV2;
+import org.neo4j.bolt.v3.BoltStateMachineV3;
import org.neo4j.graphdb.DependencyResolver;
import org.neo4j.kernel.AvailabilityGuard;
import org.neo4j.kernel.GraphDatabaseQueryService;
@@ -40,24 +43,50 @@
import org.neo4j.test.OnDemandJobScheduler;
import org.neo4j.udc.UsageData;
+import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class BoltStateMachineFactoryImplTest
+class BoltStateMachineFactoryImplTest
{
private static final Clock CLOCK = Clock.systemUTC();
private static final BoltChannel CHANNEL = mock( BoltChannel.class );
@ParameterizedTest( name = "V{0}" )
@ValueSource( longs = {BoltProtocolV1.VERSION, BoltProtocolV2.VERSION} )
- public void shouldCreateBoltStateMachines( long protocolVersion )
+ void shouldCreateBoltStateMachines( long protocolVersion )
{
BoltStateMachineFactoryImpl factory = newBoltFactory();
BoltStateMachine boltStateMachine = factory.newStateMachine( protocolVersion, CHANNEL );
assertNotNull( boltStateMachine );
+ assertThat( boltStateMachine, instanceOf( BoltStateMachineV1.class ) );
+ }
+
+ @Test
+ void shouldCreateBoltStateMachinesV3()
+ {
+ BoltStateMachineFactoryImpl factory = newBoltFactory();
+
+ BoltStateMachine boltStateMachine = factory.newStateMachine( 3L, CHANNEL );
+
+ assertNotNull( boltStateMachine );
+ assertThat( boltStateMachine, instanceOf( BoltStateMachineV3.class ) );
+ }
+
+ @ParameterizedTest( name = "V{0}" )
+ @ValueSource( longs = {999, -1} )
+ void shouldReturnNullIfVersionIsUnknown( long protocolVersion )
+ {
+ BoltStateMachineFactoryImpl factory = newBoltFactory();
+
+ BoltStateMachine boltStateMachine = factory.newStateMachine( protocolVersion, CHANNEL );
+
+ assertNull( boltStateMachine );
}
private static BoltStateMachineFactoryImpl newBoltFactory()
diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v3/BoltProtocolV3Test.java b/community/bolt/src/test/java/org/neo4j/bolt/v3/BoltProtocolV3Test.java
new file mode 100644
index 0000000000000..27ce9da95375a
--- /dev/null
+++ b/community/bolt/src/test/java/org/neo4j/bolt/v3/BoltProtocolV3Test.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3;
+
+import org.junit.jupiter.api.Test;
+
+import org.neo4j.bolt.BoltChannel;
+import org.neo4j.bolt.messaging.Neo4jPack;
+import org.neo4j.bolt.runtime.BoltConnection;
+import org.neo4j.bolt.runtime.BoltStateMachineFactory;
+import org.neo4j.bolt.v2.messaging.Neo4jPackV2;
+import org.neo4j.bolt.v3.messaging.BoltRequestMessageReaderV3;
+import org.neo4j.kernel.impl.logging.NullLogService;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.mock;
+
+class BoltProtocolV3Test
+{
+ @Test
+ void shouldCreatePackForBoltV3()
+ {
+ BoltProtocolV3 protocolV3 =
+ new BoltProtocolV3( mock( BoltChannel.class ), ( ch, st ) -> mock( BoltConnection.class ), mock( BoltStateMachineFactory.class ),
+ NullLogService.getInstance() );
+
+ assertThat( protocolV3.createPack(), instanceOf( Neo4jPackV2.class ) );
+ }
+
+ @Test
+ void shouldVersionReturnBoltV3()
+ {
+ BoltProtocolV3 protocolV3 =
+ new BoltProtocolV3( mock( BoltChannel.class ), ( ch, st ) -> mock( BoltConnection.class ), mock( BoltStateMachineFactory.class ),
+ NullLogService.getInstance() );
+
+ assertThat( protocolV3.version(), equalTo( 3L ) );
+ }
+
+ @Test
+ void shouldCreateMessageReaderForBoltV3()
+ {
+ BoltProtocolV3 protocolV3 =
+ new BoltProtocolV3( mock( BoltChannel.class ), ( ch, st ) -> mock( BoltConnection.class ), mock( BoltStateMachineFactory.class ),
+ NullLogService.getInstance() );
+
+ assertThat( protocolV3.createMessageReader( mock( BoltChannel.class ), mock( Neo4jPack.class ), mock( BoltConnection.class ),
+ NullLogService.getInstance() ), instanceOf( BoltRequestMessageReaderV3.class ) );
+ }
+}
diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/BoltProtocolV3ComponentFactory.java b/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/BoltProtocolV3ComponentFactory.java
new file mode 100644
index 0000000000000..bf7cbf6dcb8cb
--- /dev/null
+++ b/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/BoltProtocolV3ComponentFactory.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3.messaging;
+
+import java.io.IOException;
+
+import org.neo4j.bolt.logging.NullBoltMessageLogger;
+import org.neo4j.bolt.messaging.BoltRequestMessageReader;
+import org.neo4j.bolt.messaging.BoltResponseMessageWriter;
+import org.neo4j.bolt.messaging.Neo4jPack;
+import org.neo4j.bolt.messaging.RequestMessage;
+import org.neo4j.bolt.runtime.BoltStateMachine;
+import org.neo4j.bolt.runtime.SynchronousBoltConnection;
+import org.neo4j.bolt.v1.messaging.BoltRequestMessageWriter;
+import org.neo4j.bolt.v1.messaging.RecordingByteChannel;
+import org.neo4j.bolt.v1.packstream.BufferedChannelOutput;
+import org.neo4j.bolt.v2.messaging.Neo4jPackV2;
+import org.neo4j.kernel.impl.logging.NullLogService;
+
+import static org.mockito.Mockito.mock;
+
+/**
+ * A helper factory to generate boltV3 component in tests
+ */
+public class BoltProtocolV3ComponentFactory
+{
+ public static Neo4jPack neo4jPack()
+ {
+ return new Neo4jPackV2();
+ }
+
+ public static BoltRequestMessageWriter requestMessageWriter( Neo4jPack.Packer packer )
+ {
+ return new BoltRequestMessageWriterV3( packer );
+ }
+
+ public static BoltRequestMessageReader requestMessageReader( BoltStateMachine stateMachine )
+ {
+ return new BoltRequestMessageReaderV3( new SynchronousBoltConnection( stateMachine ),
+ mock( BoltResponseMessageWriter.class ), NullBoltMessageLogger.getInstance(), NullLogService.getInstance() );
+ }
+
+ public static byte[] encode( Neo4jPack neo4jPack, RequestMessage... messages ) throws IOException
+ {
+ RecordingByteChannel rawData = new RecordingByteChannel();
+ Neo4jPack.Packer packer = neo4jPack.newPacker( new BufferedChannelOutput( rawData ) );
+ BoltRequestMessageWriter writer = requestMessageWriter( packer );
+
+ for ( RequestMessage message : messages )
+ {
+ writer.write( message );
+ }
+ writer.flush();
+
+ return rawData.getBytes();
+ }
+
+}
diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/BoltRequestMessageReaderV3Test.java b/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/BoltRequestMessageReaderV3Test.java
new file mode 100644
index 0000000000000..aebb2a94315cf
--- /dev/null
+++ b/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/BoltRequestMessageReaderV3Test.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3.messaging;
+
+import org.junit.jupiter.api.Test;
+
+import org.neo4j.bolt.messaging.BoltIOException;
+import org.neo4j.bolt.messaging.BoltRequestMessageReader;
+import org.neo4j.bolt.messaging.Neo4jPack;
+import org.neo4j.bolt.messaging.RequestMessage;
+import org.neo4j.bolt.runtime.BoltStateMachine;
+import org.neo4j.bolt.v1.messaging.request.InitMessage;
+import org.neo4j.bolt.v1.packstream.PackedInputArray;
+
+import static org.hamcrest.CoreMatchers.startsWith;
+import static org.junit.Assert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.neo4j.bolt.v3.messaging.BoltProtocolV3ComponentFactory.encode;
+import static org.neo4j.bolt.v3.messaging.BoltProtocolV3ComponentFactory.neo4jPack;
+import static org.neo4j.helpers.collection.MapUtil.map;
+
+class BoltRequestMessageReaderV3Test
+{
+ @Test
+ void shouldDecodeHelloMessage() throws Exception
+ {
+ testMessageDecoding( new HelloMessage( map( "user_agent", "My driver", "one", 1L, "two", 2L ) ) );
+ }
+
+ @Test
+ void shouldNotDecodeInitMessage() throws Exception
+ {
+ BoltIOException exception =
+ assertThrows( BoltIOException.class, () -> testMessageDecoding( new InitMessage( "My driver", map( "one", 1L, "two", 2L ) ) ) );
+ assertThat( exception.getMessage(), startsWith( "Unable to read message type." ) );
+ }
+
+ private static void testMessageDecoding( RequestMessage message ) throws Exception
+ {
+ Neo4jPack neo4jPack = neo4jPack();
+
+ BoltStateMachine stateMachine = mock( BoltStateMachine.class );
+ BoltRequestMessageReader reader = BoltProtocolV3ComponentFactory.requestMessageReader( stateMachine );
+
+ PackedInputArray innput = new PackedInputArray( encode( neo4jPack, message ) );
+ Neo4jPack.Unpacker unpacker = neo4jPack.newUnpacker( innput );
+
+ reader.read( unpacker );
+
+ verify( stateMachine ).process( eq( message ), any() );
+ }
+}
diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/BoltRequestMessageWriterV3.java b/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/BoltRequestMessageWriterV3.java
new file mode 100644
index 0000000000000..c2ff2e3607e62
--- /dev/null
+++ b/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/BoltRequestMessageWriterV3.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3.messaging;
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+
+import org.neo4j.bolt.messaging.Neo4jPack;
+import org.neo4j.bolt.messaging.RequestMessage;
+import org.neo4j.bolt.v1.messaging.BoltRequestMessageWriter;
+import org.neo4j.kernel.impl.util.ValueUtils;
+
+/**
+ * This writer simulates the client.
+ */
+public class BoltRequestMessageWriterV3 extends BoltRequestMessageWriter
+{
+ public BoltRequestMessageWriterV3( Neo4jPack.Packer packer )
+ {
+ super( packer );
+ }
+
+ @Override
+ public BoltRequestMessageWriter write( RequestMessage message ) throws IOException
+ {
+ if ( message instanceof HelloMessage )
+ {
+ writeHello( (HelloMessage) message );
+ }
+ return super.write( message );
+ }
+
+ private void writeHello( HelloMessage message )
+ {
+ try
+ {
+ packer.packStructHeader( 0, HelloMessage.SIGNATURE );
+ packer.pack( ValueUtils.asMapValue( message.meta() ) );
+ }
+ catch ( IOException e )
+ {
+ throw new UncheckedIOException( e );
+ }
+ }
+}
diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/HelloMessageDecoderTest.java b/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/HelloMessageDecoderTest.java
new file mode 100644
index 0000000000000..c9ef4ec41d0c5
--- /dev/null
+++ b/community/bolt/src/test/java/org/neo4j/bolt/v3/messaging/HelloMessageDecoderTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3.messaging;
+
+import org.junit.jupiter.api.Test;
+
+import org.neo4j.bolt.logging.BoltMessageLogger;
+import org.neo4j.bolt.messaging.Neo4jPack;
+import org.neo4j.bolt.messaging.RequestMessage;
+import org.neo4j.bolt.messaging.RequestMessageDecoder;
+import org.neo4j.bolt.runtime.BoltResponseHandler;
+import org.neo4j.bolt.v1.packstream.PackedInputArray;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.neo4j.bolt.v3.messaging.BoltProtocolV3ComponentFactory.encode;
+import static org.neo4j.bolt.v3.messaging.BoltProtocolV3ComponentFactory.neo4jPack;
+import static org.neo4j.helpers.collection.MapUtil.map;
+
+class HelloMessageDecoderTest
+{
+ private final BoltResponseHandler responseHandler = mock( BoltResponseHandler.class );
+ private final BoltMessageLogger messageLogger = mock( BoltMessageLogger.class );
+ private final RequestMessageDecoder decoder = new HelloMessageDecoder( responseHandler, messageLogger );
+
+ @Test
+ void shouldReturnCorrectSignature()
+ {
+ assertEquals( HelloMessage.SIGNATURE, decoder.signature() );
+ }
+
+ @Test
+ void shouldReturnConnectResponseHandler()
+ {
+ assertEquals( responseHandler, decoder.responseHandler() );
+ }
+
+ @Test
+ void shouldDecodeAckFailure() throws Exception
+ {
+ Neo4jPack neo4jPack = neo4jPack();
+ HelloMessage originalMessage = new HelloMessage( map( "user_agent", "My Driver", "user", "neo4j", "password", "secret" ) );
+
+ PackedInputArray innput = new PackedInputArray( encode( neo4jPack, originalMessage ) );
+ Neo4jPack.Unpacker unpacker = neo4jPack.newUnpacker( innput );
+
+ // these two steps are executed before decoding in order to select a correct decoder
+ unpacker.unpackStructHeader();
+ unpacker.unpackStructSignature();
+
+ RequestMessage deserializedMessage = decoder.decode( unpacker );
+ assertEquals( originalMessage, deserializedMessage );
+ }
+}
diff --git a/community/bolt/src/test/java/org/neo4j/bolt/v3/runtime/ExtraMetaDataConnectedStateTest.java b/community/bolt/src/test/java/org/neo4j/bolt/v3/runtime/ExtraMetaDataConnectedStateTest.java
new file mode 100644
index 0000000000000..2ed3982a6d1b9
--- /dev/null
+++ b/community/bolt/src/test/java/org/neo4j/bolt/v3/runtime/ExtraMetaDataConnectedStateTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2002-2018 "Neo4j,"
+ * Neo4j Sweden AB [http://neo4j.com]
+ *
+ * This file is part of Neo4j.
+ *
+ * Neo4j is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.neo4j.bolt.v3.runtime;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+
+import org.neo4j.bolt.runtime.BoltStateMachineSPI;
+import org.neo4j.bolt.runtime.BoltStateMachineState;
+import org.neo4j.bolt.runtime.MutableConnectionState;
+import org.neo4j.bolt.runtime.StateMachineContext;
+import org.neo4j.bolt.security.auth.AuthenticationResult;
+import org.neo4j.bolt.v1.runtime.ConnectedState;
+import org.neo4j.bolt.v3.messaging.HelloMessage;
+import org.neo4j.values.storable.StringValue;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.RETURNS_MOCKS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.neo4j.helpers.collection.MapUtil.map;
+import static org.neo4j.kernel.api.security.AuthToken.CREDENTIALS;
+import static org.neo4j.kernel.api.security.AuthToken.PRINCIPAL;
+import static org.neo4j.values.storable.Values.stringValue;
+
+class ExtraMetaDataConnectedStateTest
+{
+ @Test
+ void shouldAddServerVersionMetadataOnHelloMessage() throws Exception
+ {
+ // Given
+ // hello message
+ Map meta = map( "user_agent", "3.0", PRINCIPAL, "neo4j", CREDENTIALS, "password" );
+ HelloMessage helloMessage = new HelloMessage( meta );
+
+ // setup state machine
+ ConnectedState state = new ExtraMetaDataConnectedState();
+ BoltStateMachineState readyState = mock( BoltStateMachineState.class );
+ BoltStateMachineState failedState = mock( BoltStateMachineState.class );
+
+ StateMachineContext context = mock( StateMachineContext.class );
+ BoltStateMachineSPI boltSpi = mock( BoltStateMachineSPI.class, RETURNS_MOCKS );
+ MutableConnectionState connectionState = new MutableConnectionState();
+
+ state.setReadyState( readyState );
+ state.setFailedState( failedState );
+
+ when( context.boltSpi() ).thenReturn( boltSpi );
+ when( context.connectionState() ).thenReturn( connectionState );
+
+ when( boltSpi.version() ).thenReturn( "42.42.42" );
+ MutableConnectionState connectionStateMock = mock( MutableConnectionState.class );
+ when( context.connectionState() ).thenReturn( connectionStateMock );
+ when( context.connectionId() ).thenReturn( "connection-uuid" );
+
+ AuthenticationResult authResult = mock( AuthenticationResult.class );
+ when( authResult.credentialsExpired() ).thenReturn( true );
+ when( boltSpi.authenticate( meta ) ).thenReturn( authResult );
+
+ // When
+ BoltStateMachineState newState = state.process( helloMessage, context );
+
+ // Then
+ assertEquals( readyState, newState );
+ verify( connectionStateMock ).onMetadata( "server", stringValue( "42.42.42" ) );
+ verify( connectionStateMock ).onMetadata( "routing_table", stringValue( "dbms.cluster.routing.getRoutingTable" ) );
+ verify( connectionStateMock ).onMetadata( eq( "connection_id" ), any( StringValue.class ) );
+ }
+}
diff --git a/community/community-it/it-test-support/src/main/java/org/neo4j/bolt/v1/runtime/integration/SessionRule.java b/community/community-it/it-test-support/src/main/java/org/neo4j/bolt/v1/runtime/integration/SessionRule.java
index 1df546d57826e..46e4abd86332f 100644
--- a/community/community-it/it-test-support/src/main/java/org/neo4j/bolt/v1/runtime/integration/SessionRule.java
+++ b/community/community-it/it-test-support/src/main/java/org/neo4j/bolt/v1/runtime/integration/SessionRule.java
@@ -36,7 +36,7 @@
import org.neo4j.bolt.runtime.BoltStateMachine;
import org.neo4j.bolt.security.auth.Authentication;
import org.neo4j.bolt.security.auth.BasicAuthentication;
-import org.neo4j.bolt.v1.runtime.BoltStateMachineFactoryImpl;
+import org.neo4j.bolt.runtime.BoltStateMachineFactoryImpl;
import org.neo4j.bolt.v2.BoltProtocolV2;
import org.neo4j.graphdb.DependencyResolver;
import org.neo4j.graphdb.config.Setting;