From 6c28d453ee9dd05412a9dbad66336a062e20a3cf Mon Sep 17 00:00:00 2001 From: "ASP.NET CI" Date: Sun, 15 Jul 2018 12:28:22 -0700 Subject: [PATCH 1/2] Update dependencies.props [auto-updated: dependencies] --- build/dependencies.props | 112 +++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/build/dependencies.props b/build/dependencies.props index 79e22435c1..49ab41702b 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,72 +5,72 @@ 0.10.13 3.1.0 - 2.2.0-preview1-34640 + 2.2.0-preview1-34694 2.2.0-preview1-17099 1.7.3.4 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 4.6.0-preview1-26617-01 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 - 2.2.0-preview1-34640 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 4.5.0 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 + 2.2.0-preview1-34694 2.2.0-preview1-26618-02 15.6.1 4.7.49 2.0.3 11.0.2 1.2.6 - 4.6.0-preview1-26617-01 - 4.6.0-preview1-26617-01 - 4.6.0-preview1-26617-01 - 4.6.0-preview1-26617-01 + 4.5.0 + 4.5.0 + 4.5.1 + 4.5.0 3.1.1 4.3.0 - 4.6.0-preview1-26617-01 - 4.6.0-preview1-26617-01 - 4.6.0-preview1-26617-01 + 4.5.1 + 4.5.0 + 4.5.1 2.3.1 2.3.1 2.3.1 From 25c65a5d85f11d498bbace628f72388c44905943 Mon Sep 17 00:00:00 2001 From: Mikael Mengistu Date: Mon, 16 Jul 2018 11:15:28 -0700 Subject: [PATCH 2/2] Add HubMessage abstraction and parse messages from the server into different message types (#2620) --- .../signalr/src/main/java/HubConnection.java | 35 ++++--- .../signalr/src/main/java/HubMessage.java | 6 ++ .../signalr/src/main/java/HubMessageType.java | 15 +++ .../signalr/src/main/java/HubProtocol.java | 2 +- .../src/main/java/InvocationMessage.java | 9 +- .../src/main/java/JsonHubProtocol.java | 38 ++++---- .../signalr/src/main/java/PingMessage.java | 12 +++ .../src/test/java/JsonHubProtocolTest.java | 96 +++++++++++++------ 8 files changed, 150 insertions(+), 63 deletions(-) create mode 100644 clients/java/signalr/src/main/java/HubMessage.java create mode 100644 clients/java/signalr/src/main/java/HubMessageType.java create mode 100644 clients/java/signalr/src/main/java/PingMessage.java diff --git a/clients/java/signalr/src/main/java/HubConnection.java b/clients/java/signalr/src/main/java/HubConnection.java index 28a65e45dc..7e0f6c5852 100644 --- a/clients/java/signalr/src/main/java/HubConnection.java +++ b/clients/java/signalr/src/main/java/HubConnection.java @@ -23,19 +23,32 @@ public class HubConnection { this.protocol = new JsonHubProtocol(); 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. - // Adding this to avoid getting error messages on pings for now. - for (InvocationMessage message : messages) { - if (message != null && handlers.containsKey(message.target)) { - ArrayList args = gson.fromJson((JsonArray)message.arguments[0], (new ArrayList()).getClass()); - List actions = handlers.get(message.target); - if (actions != null) { - for (ActionBase action: actions) { - action.invoke(args.toArray()); + for (HubMessage message : messages) { + switch (message.getMessageType()) { + case INVOCATION: + InvocationMessage invocationMessage = (InvocationMessage)message; + if (message != null && handlers.containsKey(invocationMessage.target)) { + ArrayList args = gson.fromJson((JsonArray)invocationMessage.arguments[0], (new ArrayList()).getClass()); + List actions = handlers.get(invocationMessage.target); + if (actions != null) { + 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; } } }; diff --git a/clients/java/signalr/src/main/java/HubMessage.java b/clients/java/signalr/src/main/java/HubMessage.java new file mode 100644 index 0000000000..2c5e20175f --- /dev/null +++ b/clients/java/signalr/src/main/java/HubMessage.java @@ -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(); +} diff --git a/clients/java/signalr/src/main/java/HubMessageType.java b/clients/java/signalr/src/main/java/HubMessageType.java new file mode 100644 index 0000000000..d18e3b9f6b --- /dev/null +++ b/clients/java/signalr/src/main/java/HubMessageType.java @@ -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; } +} diff --git a/clients/java/signalr/src/main/java/HubProtocol.java b/clients/java/signalr/src/main/java/HubProtocol.java index 06413f5111..39f184e84c 100644 --- a/clients/java/signalr/src/main/java/HubProtocol.java +++ b/clients/java/signalr/src/main/java/HubProtocol.java @@ -5,7 +5,7 @@ public interface HubProtocol { String getName(); int getVersion(); TransferFormat getTransferFormat(); - InvocationMessage[] parseMessages(String message); + HubMessage[] parseMessages(String message); String writeMessage(InvocationMessage message); } diff --git a/clients/java/signalr/src/main/java/InvocationMessage.java b/clients/java/signalr/src/main/java/InvocationMessage.java index 258d57a058..635067ff2e 100644 --- a/clients/java/signalr/src/main/java/InvocationMessage.java +++ b/clients/java/signalr/src/main/java/InvocationMessage.java @@ -1,8 +1,8 @@ // 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 InvocationMessage { - int type = 1; +public class InvocationMessage extends HubMessage { + int type = HubMessageType.INVOCATION.value; String invocationId; String target; Object[] arguments; @@ -35,4 +35,9 @@ public class InvocationMessage { public void setArguments(Object[] arguments) { this.arguments = arguments; } + + @Override + HubMessageType getMessageType() { + return HubMessageType.INVOCATION; + } } diff --git a/clients/java/signalr/src/main/java/JsonHubProtocol.java b/clients/java/signalr/src/main/java/JsonHubProtocol.java index 8e5ddd71ee..fcc4b4a2e4 100644 --- a/clients/java/signalr/src/main/java/JsonHubProtocol.java +++ b/clients/java/signalr/src/main/java/JsonHubProtocol.java @@ -30,9 +30,9 @@ public class JsonHubProtocol implements HubProtocol { } @Override - public InvocationMessage[] parseMessages(String payload) { + public HubMessage[] parseMessages(String payload) { String[] messages = payload.split(RECORD_SEPARATOR); - List invocationMessages = new ArrayList<>(); + List hubMessages = new ArrayList<>(); for (String splitMessage : messages) { // Empty handshake response "{}". We can ignore it if (splitMessage.equals("{}")) { @@ -40,41 +40,35 @@ public class JsonHubProtocol implements HubProtocol { } JsonObject jsonMessage = jsonParser.parse(splitMessage).getAsJsonObject(); - String messageType = jsonMessage.get("type").toString(); + HubMessageType messageType = HubMessageType.values()[jsonMessage.get("type").getAsInt() -1]; switch (messageType) { - case "1": + case INVOCATION: //Invocation Message String target = jsonMessage.get("target").getAsString(); JsonElement args = jsonMessage.get("arguments"); - invocationMessages.add(new InvocationMessage(target, new Object[] {args})); + hubMessages.add(new InvocationMessage(target, new Object[] {args})); break; - case "2": - //Stream item + case STREAM_ITEM: + throw new UnsupportedOperationException("Support for streaming is not yet available"); + case COMPLETION: //Don't care yet break; - case "3": - //Completion - //Don't care yet - break; - case "4": - //Stream invocation + case STREAM_INVOCATION: //Don't care yet; + throw new UnsupportedOperationException("Support for streaming is not yet available"); + case CANCEL_INVOCATION: + // Not tracking invocations yet break; - case "5": - //Cancel invocation - //Don't care yet - break; - case "6": + case PING: //Ping - //Don't care yet + hubMessages.add(new PingMessage()); break; - case "7": - // Close message + case CLOSE: //Don't care yet; break; } } - return invocationMessages.toArray(new InvocationMessage[invocationMessages.size()]); + return hubMessages.toArray(new HubMessage[hubMessages.size()]); } @Override diff --git a/clients/java/signalr/src/main/java/PingMessage.java b/clients/java/signalr/src/main/java/PingMessage.java new file mode 100644 index 0000000000..6bf9be7753 --- /dev/null +++ b/clients/java/signalr/src/main/java/PingMessage.java @@ -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; + } +} diff --git a/clients/java/signalr/src/test/java/JsonHubProtocolTest.java b/clients/java/signalr/src/test/java/JsonHubProtocolTest.java index dbdbbe2e05..ce29d57c35 100644 --- a/clients/java/signalr/src/test/java/JsonHubProtocolTest.java +++ b/clients/java/signalr/src/test/java/JsonHubProtocolTest.java @@ -2,7 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. import com.google.gson.JsonArray; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import static org.junit.Assert.*; @@ -34,30 +36,63 @@ public class JsonHubProtocolTest { } @Test - public void ParseSingleMessage() { - String stringifiedMessage = "{\"type\":1,\"target\":\"test\",\"arguments\":[42]}\u001E"; - InvocationMessage[] messages = jsonHubProtocol.parseMessages(stringifiedMessage); + public void ParsePingMessage() { + String stringifiedMessage = "{\"type\":6}\u001E"; + HubMessage[] messages = jsonHubProtocol.parseMessages(stringifiedMessage); //We know it's only one message assertEquals(1, messages.length); - InvocationMessage message = messages[0]; - assertEquals("test", message.target); - assertEquals(null, message.invocationId); - assertEquals(1, message.type); - JsonArray messageResult = (JsonArray) message.arguments[0]; + assertEquals(HubMessageType.PING, messages[0].getMessageType()); + } + + @Test + 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()); } + @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 public void ParseHandshakeResponsePlusMessage() { 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 - InvocationMessage message = messages[0]; + //We ignore the Handshake response for now and we can cast because we know we have in invocation message. + InvocationMessage message = (InvocationMessage) messages[0]; assertEquals("test", message.target); - assertEquals(null, message.invocationId); - assertEquals(1, message.type); JsonArray messageResult = (JsonArray) message.arguments[0]; assertEquals(42, messageResult.getAsInt()); } @@ -65,36 +100,43 @@ public class JsonHubProtocolTest { @Test public void ParseTwoMessages() { 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); // Check the first message - InvocationMessage message = messages[0]; - assertEquals("one", message.target); - assertEquals(null, message.invocationId); - assertEquals(1, message.type); - JsonArray messageResult = (JsonArray) message.arguments[0]; + assertEquals(HubMessageType.INVOCATION, messages[0].getMessageType()); + + //Now that we know we have an invocation message we can cast the hubMessage. + InvocationMessage invocationMessage = (InvocationMessage) messages[0]; + + assertEquals("one", invocationMessage.target); + assertEquals(null, invocationMessage.invocationId); + JsonArray messageResult = (JsonArray) invocationMessage.arguments[0]; assertEquals(42, messageResult.getAsInt()); // Check the second message - InvocationMessage secondMessage = messages[1]; - assertEquals("two", secondMessage.target); - assertEquals(null, secondMessage.invocationId); - assertEquals(1, secondMessage.type); - JsonArray secondMessageResult = (JsonArray) secondMessage.arguments[0]; + assertEquals(HubMessageType.INVOCATION, messages[1].getMessageType()); + + //Now that we know we have an invocation message we can cast the hubMessage. + InvocationMessage invocationMessage2 = (InvocationMessage) messages[1]; + + assertEquals("two", invocationMessage2.target); + assertEquals(null, invocationMessage2.invocationId); + JsonArray secondMessageResult = (JsonArray) invocationMessage2.arguments[0]; assertEquals(43, secondMessageResult.getAsInt()); } @Test public void ParseSingleMessageMutipleArgs() { 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 - InvocationMessage message = messages[0]; + assertEquals(HubMessageType.INVOCATION, messages[0].getMessageType()); + + InvocationMessage message = (InvocationMessage)messages[0]; assertEquals("test", message.target); assertEquals(null, message.invocationId); - assertEquals(1, message.type); JsonArray messageResult = ((JsonArray) message.arguments[0]); assertEquals(42, messageResult.get(0).getAsInt()); assertEquals(24, messageResult.get(1).getAsInt());