Merge branch 'release/2.2'
This commit is contained in:
commit
f732279b39
|
|
@ -23,19 +23,32 @@ public class HubConnection {
|
||||||
this.protocol = new JsonHubProtocol();
|
this.protocol = new JsonHubProtocol();
|
||||||
this.callback = (payload) -> {
|
this.callback = (payload) -> {
|
||||||
|
|
||||||
InvocationMessage[] messages = protocol.parseMessages(payload);
|
HubMessage[] messages = protocol.parseMessages(payload);
|
||||||
|
|
||||||
// message will be null if we receive any message other than an invocation.
|
for (HubMessage message : messages) {
|
||||||
// Adding this to avoid getting error messages on pings for now.
|
switch (message.getMessageType()) {
|
||||||
for (InvocationMessage message : messages) {
|
case INVOCATION:
|
||||||
if (message != null && handlers.containsKey(message.target)) {
|
InvocationMessage invocationMessage = (InvocationMessage)message;
|
||||||
ArrayList<Object> args = gson.fromJson((JsonArray)message.arguments[0], (new ArrayList<Object>()).getClass());
|
if (message != null && handlers.containsKey(invocationMessage.target)) {
|
||||||
List<ActionBase> actions = handlers.get(message.target);
|
ArrayList<Object> args = gson.fromJson((JsonArray)invocationMessage.arguments[0], (new ArrayList<Object>()).getClass());
|
||||||
if (actions != null) {
|
List<ActionBase> actions = handlers.get(invocationMessage.target);
|
||||||
for (ActionBase action: actions) {
|
if (actions != null) {
|
||||||
action.invoke(args.toArray());
|
for (ActionBase action: actions) {
|
||||||
|
action.invoke(args.toArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
case STREAM_INVOCATION:
|
||||||
|
case STREAM_ITEM:
|
||||||
|
throw new UnsupportedOperationException("Streaming is not yet supported");
|
||||||
|
case CLOSE:
|
||||||
|
case CANCEL_INVOCATION:
|
||||||
|
case COMPLETION:
|
||||||
|
case PING:
|
||||||
|
// We don't need to do anything in the case of a ping message.
|
||||||
|
// The other message types aren't supported
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
public abstract class HubMessage {
|
||||||
|
abstract HubMessageType getMessageType();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
public enum HubMessageType {
|
||||||
|
INVOCATION(1),
|
||||||
|
STREAM_ITEM(2),
|
||||||
|
COMPLETION(3),
|
||||||
|
STREAM_INVOCATION(4),
|
||||||
|
CANCEL_INVOCATION(5),
|
||||||
|
PING(6),
|
||||||
|
CLOSE(7);
|
||||||
|
|
||||||
|
public int value;
|
||||||
|
HubMessageType(int id) { this.value = id; }
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ public interface HubProtocol {
|
||||||
String getName();
|
String getName();
|
||||||
int getVersion();
|
int getVersion();
|
||||||
TransferFormat getTransferFormat();
|
TransferFormat getTransferFormat();
|
||||||
InvocationMessage[] parseMessages(String message);
|
HubMessage[] parseMessages(String message);
|
||||||
String writeMessage(InvocationMessage message);
|
String writeMessage(InvocationMessage message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
// Copyright (c) .NET Foundation. All rights reserved.
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
public class InvocationMessage {
|
public class InvocationMessage extends HubMessage {
|
||||||
int type = 1;
|
int type = HubMessageType.INVOCATION.value;
|
||||||
String invocationId;
|
String invocationId;
|
||||||
String target;
|
String target;
|
||||||
Object[] arguments;
|
Object[] arguments;
|
||||||
|
|
@ -35,4 +35,9 @@ public class InvocationMessage {
|
||||||
public void setArguments(Object[] arguments) {
|
public void setArguments(Object[] arguments) {
|
||||||
this.arguments = arguments;
|
this.arguments = arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
HubMessageType getMessageType() {
|
||||||
|
return HubMessageType.INVOCATION;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ public class JsonHubProtocol implements HubProtocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public InvocationMessage[] parseMessages(String payload) {
|
public HubMessage[] parseMessages(String payload) {
|
||||||
String[] messages = payload.split(RECORD_SEPARATOR);
|
String[] messages = payload.split(RECORD_SEPARATOR);
|
||||||
List<InvocationMessage> invocationMessages = new ArrayList<>();
|
List<HubMessage> hubMessages = new ArrayList<>();
|
||||||
for (String splitMessage : messages) {
|
for (String splitMessage : messages) {
|
||||||
// Empty handshake response "{}". We can ignore it
|
// Empty handshake response "{}". We can ignore it
|
||||||
if (splitMessage.equals("{}")) {
|
if (splitMessage.equals("{}")) {
|
||||||
|
|
@ -40,41 +40,35 @@ public class JsonHubProtocol implements HubProtocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject jsonMessage = jsonParser.parse(splitMessage).getAsJsonObject();
|
JsonObject jsonMessage = jsonParser.parse(splitMessage).getAsJsonObject();
|
||||||
String messageType = jsonMessage.get("type").toString();
|
HubMessageType messageType = HubMessageType.values()[jsonMessage.get("type").getAsInt() -1];
|
||||||
switch (messageType) {
|
switch (messageType) {
|
||||||
case "1":
|
case INVOCATION:
|
||||||
//Invocation Message
|
//Invocation Message
|
||||||
String target = jsonMessage.get("target").getAsString();
|
String target = jsonMessage.get("target").getAsString();
|
||||||
JsonElement args = jsonMessage.get("arguments");
|
JsonElement args = jsonMessage.get("arguments");
|
||||||
invocationMessages.add(new InvocationMessage(target, new Object[] {args}));
|
hubMessages.add(new InvocationMessage(target, new Object[] {args}));
|
||||||
break;
|
break;
|
||||||
case "2":
|
case STREAM_ITEM:
|
||||||
//Stream item
|
throw new UnsupportedOperationException("Support for streaming is not yet available");
|
||||||
|
case COMPLETION:
|
||||||
//Don't care yet
|
//Don't care yet
|
||||||
break;
|
break;
|
||||||
case "3":
|
case STREAM_INVOCATION:
|
||||||
//Completion
|
|
||||||
//Don't care yet
|
|
||||||
break;
|
|
||||||
case "4":
|
|
||||||
//Stream invocation
|
|
||||||
//Don't care yet;
|
//Don't care yet;
|
||||||
|
throw new UnsupportedOperationException("Support for streaming is not yet available");
|
||||||
|
case CANCEL_INVOCATION:
|
||||||
|
// Not tracking invocations yet
|
||||||
break;
|
break;
|
||||||
case "5":
|
case PING:
|
||||||
//Cancel invocation
|
|
||||||
//Don't care yet
|
|
||||||
break;
|
|
||||||
case "6":
|
|
||||||
//Ping
|
//Ping
|
||||||
//Don't care yet
|
hubMessages.add(new PingMessage());
|
||||||
break;
|
break;
|
||||||
case "7":
|
case CLOSE:
|
||||||
// Close message
|
|
||||||
//Don't care yet;
|
//Don't care yet;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return invocationMessages.toArray(new InvocationMessage[invocationMessages.size()]);
|
return hubMessages.toArray(new HubMessage[hubMessages.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
public class PingMessage extends HubMessage {
|
||||||
|
|
||||||
|
int type = HubMessageType.PING.value;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
HubMessageType getMessageType() {
|
||||||
|
return HubMessageType.PING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,9 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
|
@ -34,30 +36,63 @@ public class JsonHubProtocolTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ParseSingleMessage() {
|
public void ParsePingMessage() {
|
||||||
String stringifiedMessage = "{\"type\":1,\"target\":\"test\",\"arguments\":[42]}\u001E";
|
String stringifiedMessage = "{\"type\":6}\u001E";
|
||||||
InvocationMessage[] messages = jsonHubProtocol.parseMessages(stringifiedMessage);
|
HubMessage[] messages = jsonHubProtocol.parseMessages(stringifiedMessage);
|
||||||
|
|
||||||
//We know it's only one message
|
//We know it's only one message
|
||||||
assertEquals(1, messages.length);
|
assertEquals(1, messages.length);
|
||||||
InvocationMessage message = messages[0];
|
assertEquals(HubMessageType.PING, messages[0].getMessageType());
|
||||||
assertEquals("test", message.target);
|
}
|
||||||
assertEquals(null, message.invocationId);
|
|
||||||
assertEquals(1, message.type);
|
@Test
|
||||||
JsonArray messageResult = (JsonArray) message.arguments[0];
|
public void ParseSingleMessage() {
|
||||||
|
String stringifiedMessage = "{\"type\":1,\"target\":\"test\",\"arguments\":[42]}\u001E";
|
||||||
|
HubMessage[] messages = jsonHubProtocol.parseMessages(stringifiedMessage);
|
||||||
|
|
||||||
|
//We know it's only one message
|
||||||
|
assertEquals(1, messages.length);
|
||||||
|
|
||||||
|
assertEquals(HubMessageType.INVOCATION, messages[0].getMessageType());
|
||||||
|
|
||||||
|
//We can safely cast here because we know that it's an invocation message.
|
||||||
|
InvocationMessage invocationMessage = (InvocationMessage) messages[0];
|
||||||
|
|
||||||
|
assertEquals("test", invocationMessage.target);
|
||||||
|
assertEquals(null, invocationMessage.invocationId);
|
||||||
|
|
||||||
|
JsonArray messageResult = (JsonArray) invocationMessage.arguments[0];
|
||||||
assertEquals(42, messageResult.getAsInt());
|
assertEquals(42, messageResult.getAsInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ExpectedException exceptionRule = ExpectedException.none();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ParseSingleUnsupportedStreamItemMessage() {
|
||||||
|
exceptionRule.expect(UnsupportedOperationException.class);
|
||||||
|
exceptionRule.expectMessage("Support for streaming is not yet available");
|
||||||
|
String stringifiedMessage = "{\"type\":2,\"Id\":1,\"Item\":42}\u001E";
|
||||||
|
HubMessage[] messages = jsonHubProtocol.parseMessages(stringifiedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ParseSingleUnsupportedStreamInvocationMessage() {
|
||||||
|
exceptionRule.expect(UnsupportedOperationException.class);
|
||||||
|
exceptionRule.expectMessage("Support for streaming is not yet available");
|
||||||
|
String stringifiedMessage = "{\"type\":4,\"Id\":1,\"target\":\"test\",\"arguments\":[42]}\u001E";
|
||||||
|
HubMessage[] messages = jsonHubProtocol.parseMessages(stringifiedMessage);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ParseHandshakeResponsePlusMessage() {
|
public void ParseHandshakeResponsePlusMessage() {
|
||||||
String twoMessages = "{}\u001E{\"type\":1,\"target\":\"test\",\"arguments\":[42]}\u001E";
|
String twoMessages = "{}\u001E{\"type\":1,\"target\":\"test\",\"arguments\":[42]}\u001E";
|
||||||
InvocationMessage[] messages = jsonHubProtocol.parseMessages(twoMessages);
|
HubMessage[] messages = jsonHubProtocol.parseMessages(twoMessages);
|
||||||
|
assertEquals(HubMessageType.INVOCATION, messages[0].getMessageType());
|
||||||
|
|
||||||
//We ignore the Handshake response for now
|
//We ignore the Handshake response for now and we can cast because we know we have in invocation message.
|
||||||
InvocationMessage message = messages[0];
|
InvocationMessage message = (InvocationMessage) messages[0];
|
||||||
assertEquals("test", message.target);
|
assertEquals("test", message.target);
|
||||||
assertEquals(null, message.invocationId);
|
|
||||||
assertEquals(1, message.type);
|
|
||||||
JsonArray messageResult = (JsonArray) message.arguments[0];
|
JsonArray messageResult = (JsonArray) message.arguments[0];
|
||||||
assertEquals(42, messageResult.getAsInt());
|
assertEquals(42, messageResult.getAsInt());
|
||||||
}
|
}
|
||||||
|
|
@ -65,36 +100,43 @@ public class JsonHubProtocolTest {
|
||||||
@Test
|
@Test
|
||||||
public void ParseTwoMessages() {
|
public void ParseTwoMessages() {
|
||||||
String twoMessages = "{\"type\":1,\"target\":\"one\",\"arguments\":[42]}\u001E{\"type\":1,\"target\":\"two\",\"arguments\":[43]}\u001E";
|
String twoMessages = "{\"type\":1,\"target\":\"one\",\"arguments\":[42]}\u001E{\"type\":1,\"target\":\"two\",\"arguments\":[43]}\u001E";
|
||||||
InvocationMessage[] messages = jsonHubProtocol.parseMessages(twoMessages);
|
HubMessage[] messages = jsonHubProtocol.parseMessages(twoMessages);
|
||||||
assertEquals(2, messages.length);
|
assertEquals(2, messages.length);
|
||||||
|
|
||||||
// Check the first message
|
// Check the first message
|
||||||
InvocationMessage message = messages[0];
|
assertEquals(HubMessageType.INVOCATION, messages[0].getMessageType());
|
||||||
assertEquals("one", message.target);
|
|
||||||
assertEquals(null, message.invocationId);
|
//Now that we know we have an invocation message we can cast the hubMessage.
|
||||||
assertEquals(1, message.type);
|
InvocationMessage invocationMessage = (InvocationMessage) messages[0];
|
||||||
JsonArray messageResult = (JsonArray) message.arguments[0];
|
|
||||||
|
assertEquals("one", invocationMessage.target);
|
||||||
|
assertEquals(null, invocationMessage.invocationId);
|
||||||
|
JsonArray messageResult = (JsonArray) invocationMessage.arguments[0];
|
||||||
assertEquals(42, messageResult.getAsInt());
|
assertEquals(42, messageResult.getAsInt());
|
||||||
|
|
||||||
// Check the second message
|
// Check the second message
|
||||||
InvocationMessage secondMessage = messages[1];
|
assertEquals(HubMessageType.INVOCATION, messages[1].getMessageType());
|
||||||
assertEquals("two", secondMessage.target);
|
|
||||||
assertEquals(null, secondMessage.invocationId);
|
//Now that we know we have an invocation message we can cast the hubMessage.
|
||||||
assertEquals(1, secondMessage.type);
|
InvocationMessage invocationMessage2 = (InvocationMessage) messages[1];
|
||||||
JsonArray secondMessageResult = (JsonArray) secondMessage.arguments[0];
|
|
||||||
|
assertEquals("two", invocationMessage2.target);
|
||||||
|
assertEquals(null, invocationMessage2.invocationId);
|
||||||
|
JsonArray secondMessageResult = (JsonArray) invocationMessage2.arguments[0];
|
||||||
assertEquals(43, secondMessageResult.getAsInt());
|
assertEquals(43, secondMessageResult.getAsInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void ParseSingleMessageMutipleArgs() {
|
public void ParseSingleMessageMutipleArgs() {
|
||||||
String stringifiedMessage = "{\"type\":1,\"target\":\"test\",\"arguments\":[42, 24]}\u001E";
|
String stringifiedMessage = "{\"type\":1,\"target\":\"test\",\"arguments\":[42, 24]}\u001E";
|
||||||
InvocationMessage[] messages = jsonHubProtocol.parseMessages(stringifiedMessage);
|
HubMessage[] messages = jsonHubProtocol.parseMessages(stringifiedMessage);
|
||||||
|
|
||||||
//We know it's only one message
|
//We know it's only one message
|
||||||
InvocationMessage message = messages[0];
|
assertEquals(HubMessageType.INVOCATION, messages[0].getMessageType());
|
||||||
|
|
||||||
|
InvocationMessage message = (InvocationMessage)messages[0];
|
||||||
assertEquals("test", message.target);
|
assertEquals("test", message.target);
|
||||||
assertEquals(null, message.invocationId);
|
assertEquals(null, message.invocationId);
|
||||||
assertEquals(1, message.type);
|
|
||||||
JsonArray messageResult = ((JsonArray) message.arguments[0]);
|
JsonArray messageResult = ((JsonArray) message.arguments[0]);
|
||||||
assertEquals(42, messageResult.get(0).getAsInt());
|
assertEquals(42, messageResult.get(0).getAsInt());
|
||||||
assertEquals(24, messageResult.get(1).getAsInt());
|
assertEquals(24, messageResult.get(1).getAsInt());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue