[Java] Throw useful error on incorrect argument length (#3010)
This commit is contained in:
parent
71ac906159
commit
13f2ebe2f6
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
package com.microsoft.aspnet.signalr;
|
package com.microsoft.aspnet.signalr;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -12,6 +13,7 @@ import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.google.gson.stream.JsonReader;
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonToken;
|
||||||
|
|
||||||
class JsonHubProtocol implements HubProtocol {
|
class JsonHubProtocol implements HubProtocol {
|
||||||
private final JsonParser jsonParser = new JsonParser();
|
private final JsonParser jsonParser = new JsonParser();
|
||||||
|
|
@ -77,15 +79,8 @@ class JsonHubProtocol implements HubProtocol {
|
||||||
break;
|
break;
|
||||||
case "arguments":
|
case "arguments":
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
reader.beginArray();
|
|
||||||
List<Class<?>> types = binder.getParameterTypes(target);
|
List<Class<?>> types = binder.getParameterTypes(target);
|
||||||
if (types != null && types.size() >= 1) {
|
arguments = bindArguments(reader, types);
|
||||||
arguments = new ArrayList<>();
|
|
||||||
for (int i = 0; i < types.size(); i++) {
|
|
||||||
arguments.add(gson.fromJson(reader, types.get(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader.endArray();
|
|
||||||
} else {
|
} else {
|
||||||
argumentsToken = (JsonArray)jsonParser.parse(reader);
|
argumentsToken = (JsonArray)jsonParser.parse(reader);
|
||||||
}
|
}
|
||||||
|
|
@ -106,12 +101,7 @@ class JsonHubProtocol implements HubProtocol {
|
||||||
case INVOCATION:
|
case INVOCATION:
|
||||||
if (argumentsToken != null) {
|
if (argumentsToken != null) {
|
||||||
List<Class<?>> types = binder.getParameterTypes(target);
|
List<Class<?>> types = binder.getParameterTypes(target);
|
||||||
if (types != null && types.size() >= 1) {
|
arguments = bindArguments(argumentsToken, types);
|
||||||
arguments = new ArrayList<>();
|
|
||||||
for (int i = 0; i < types.size(); i++) {
|
|
||||||
arguments.add(gson.fromJson(argumentsToken.get(i), types.get(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (arguments == null) {
|
if (arguments == null) {
|
||||||
hubMessages.add(new InvocationMessage(invocationId, target, new Object[0]));
|
hubMessages.add(new InvocationMessage(invocationId, target, new Object[0]));
|
||||||
|
|
@ -151,4 +141,42 @@ class JsonHubProtocol implements HubProtocol {
|
||||||
public String writeMessage(HubMessage hubMessage) {
|
public String writeMessage(HubMessage hubMessage) {
|
||||||
return gson.toJson(hubMessage) + RECORD_SEPARATOR;
|
return gson.toJson(hubMessage) + RECORD_SEPARATOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ArrayList<Object> bindArguments(JsonArray argumentsToken, List<Class<?>> paramTypes) {
|
||||||
|
if (argumentsToken.size() != paramTypes.size()) {
|
||||||
|
throw new RuntimeException(String.format("Invocation provides %d argument(s) but target expects %d.", argumentsToken.size(), paramTypes.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<Object> arguments = null;
|
||||||
|
if (paramTypes.size() >= 1) {
|
||||||
|
arguments = new ArrayList<>();
|
||||||
|
for (int i = 0; i < paramTypes.size(); i++) {
|
||||||
|
arguments.add(gson.fromJson(argumentsToken.get(i), paramTypes.get(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArrayList<Object> bindArguments(JsonReader reader, List<Class<?>> paramTypes) throws IOException {
|
||||||
|
reader.beginArray();
|
||||||
|
int paramCount = paramTypes.size();
|
||||||
|
int argCount = 0;
|
||||||
|
ArrayList<Object> arguments = new ArrayList<>();
|
||||||
|
while (reader.peek() != JsonToken.END_ARRAY) {
|
||||||
|
if (argCount < paramCount) {
|
||||||
|
arguments.add(gson.fromJson(reader, paramTypes.get(argCount)));
|
||||||
|
} else {
|
||||||
|
reader.skipValue();
|
||||||
|
}
|
||||||
|
argCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paramCount != argCount) {
|
||||||
|
throw new RuntimeException(String.format("Invocation provides %d argument(s) but target expects %d.", argCount, paramCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endArray();
|
||||||
|
return arguments;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -841,7 +841,7 @@ class HubConnectionTest {
|
||||||
@Test
|
@Test
|
||||||
public void callingStartOnStartedHubConnectionNoOps() throws Exception {
|
public void callingStartOnStartedHubConnectionNoOps() throws Exception {
|
||||||
Transport mockTransport = new MockTransport();
|
Transport mockTransport = new MockTransport();
|
||||||
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport ,new NullLogger() ,true);
|
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger() ,true);
|
||||||
hubConnection.start();
|
hubConnection.start();
|
||||||
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
|
assertEquals(HubConnectionState.CONNECTED, hubConnection.getConnectionState());
|
||||||
|
|
||||||
|
|
@ -861,4 +861,20 @@ class HubConnectionTest {
|
||||||
Throwable exception = assertThrows(HubException.class, () -> hubConnection.send("inc"));
|
Throwable exception = assertThrows(HubException.class, () -> hubConnection.send("inc"));
|
||||||
assertEquals("The 'send' method cannot be called if the connection is not active", exception.getMessage());
|
assertEquals("The 'send' method cannot be called if the connection is not active", exception.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void errorWhenReceivingInvokeWithIncorrectArgumentLength() throws Exception {
|
||||||
|
MockTransport mockTransport = new MockTransport();
|
||||||
|
HubConnection hubConnection = new HubConnection("http://example.com", mockTransport, new NullLogger(), true);
|
||||||
|
hubConnection.on("Send", (s) -> {
|
||||||
|
assertTrue(false);
|
||||||
|
}, String.class);
|
||||||
|
|
||||||
|
CompletableFuture<Void> startFuture = hubConnection.start();
|
||||||
|
mockTransport.receiveMessage("{}" + RECORD_SEPARATOR);
|
||||||
|
|
||||||
|
startFuture.get(1000, TimeUnit.MILLISECONDS);
|
||||||
|
RuntimeException exception = assertThrows(RuntimeException.class, () -> mockTransport.receiveMessage("{\"type\":1,\"target\":\"Send\",\"arguments\":[]}" + RECORD_SEPARATOR));
|
||||||
|
assertEquals("Invocation provides 0 argument(s) but target expects 1.", exception.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -219,6 +219,33 @@ class JsonHubProtocolTest {
|
||||||
assertEquals(42 , message.getResult());
|
assertEquals(42 , message.getResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void errorWhileParsingTooManyArgumentsWithOutOfOrderProperties() throws Exception {
|
||||||
|
String stringifiedMessage = "{\"arguments\":[42, 24],\"type\":1,\"target\":\"test\"}\u001E";
|
||||||
|
TestBinder binder = new TestBinder(new InvocationMessage(null, "test", new Object[] { 42 }));
|
||||||
|
|
||||||
|
RuntimeException exception = assertThrows(RuntimeException.class, () -> jsonHubProtocol.parseMessages(stringifiedMessage, binder));
|
||||||
|
assertEquals("Invocation provides 2 argument(s) but target expects 1.", exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void errorWhileParsingTooManyArguments() throws Exception {
|
||||||
|
String stringifiedMessage = "{\"type\":1,\"target\":\"test\",\"arguments\":[42, 24]}\u001E";
|
||||||
|
TestBinder binder = new TestBinder(new InvocationMessage(null, "test", new Object[] { 42 }));
|
||||||
|
|
||||||
|
RuntimeException exception = assertThrows(RuntimeException.class, () -> jsonHubProtocol.parseMessages(stringifiedMessage, binder));
|
||||||
|
assertEquals("Invocation provides 2 argument(s) but target expects 1.", exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void errorWhileParsingTooFewArguments() throws Exception {
|
||||||
|
String stringifiedMessage = "{\"type\":1,\"target\":\"test\",\"arguments\":[42]}\u001E";
|
||||||
|
TestBinder binder = new TestBinder(new InvocationMessage(null, "test", new Object[] { 42, 24 }));
|
||||||
|
|
||||||
|
RuntimeException exception = assertThrows(RuntimeException.class, () -> jsonHubProtocol.parseMessages(stringifiedMessage, binder));
|
||||||
|
assertEquals("Invocation provides 1 argument(s) but target expects 2.", exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
private class TestBinder implements InvocationBinder {
|
private class TestBinder implements InvocationBinder {
|
||||||
private Class<?>[] paramTypes = null;
|
private Class<?>[] paramTypes = null;
|
||||||
private Class<?> returnType = null;
|
private Class<?> returnType = null;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue