Merge branch 'release/2.2'

This commit is contained in:
unknown 2018-07-16 11:24:19 -07:00
commit f732279b39
8 changed files with 150 additions and 63 deletions

View File

@ -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;
} }
} }
}; };

View File

@ -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();
}

View File

@ -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; }
}

View File

@ -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);
} }

View File

@ -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;
}
} }

View File

@ -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

View File

@ -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;
}
}

View File

@ -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());