protected boolean handleCancellation(NotificationMessage notificationMessage) { if (MessageJsonHandler.CANCEL_METHOD.getMethodName().equals(notificationMessage.getMethod())) { Object cancelParams = notificationMessage.getParams(); if (cancelParams != null) { if (cancelParams instanceof CancelParams) { synchronized (receivedRequestMap) { String id = ((CancelParams) cancelParams).getId(); CompletableFuture<?> future = receivedRequestMap.get(id); if (future != null) future.cancel(true); else LOG.warning("Unmatched cancel notification for request id " + id); } return true; } else { LOG.warning("Cancellation support disabled, since the '" + MessageJsonHandler.CANCEL_METHOD.getMethodName() + "' method has been registered explicitly."); return false; } } else { LOG.warning("Missing 'params' attribute of cancel notification."); } } return false; }
@Test public void testNullResponse() throws InterruptedException, ExecutionException { Endpoint endpoint = ServiceEndpoints.toEndpoint(this); Map<String, JsonRpcMethod> methods = ServiceEndpoints.getSupportedMethods(LanguageServer.class); MessageJsonHandler handler = new MessageJsonHandler(methods); List<Message> msgs = new ArrayList<>(); MessageConsumer consumer = (message) -> { msgs.add(message); }; RemoteEndpoint re = new RemoteEndpoint(consumer, endpoint); RequestMessage request = new RequestMessage(); request.setId("1"); request.setMethod("shutdown"); re.consume(request); Assert.assertEquals("{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"result\":null}", handler.serialize(msgs.get(0))); msgs.clear(); shutdownReturn = new Object(); re.consume(request); Assert.assertEquals("{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"result\":{}}", handler.serialize(msgs.get(0))); }
@SuppressWarnings({ "unchecked" }) @Test public void testParseList() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<List<? extends Entry>>() {}.getType(), new TypeToken<List<? extends Entry>>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id)->"foo"); Message message = handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + " \"result\": [\n" + " {\"name\":\"$schema\",\"kind\":15,\"location\":{\"uri\":\"file:/home/mistria/runtime-EclipseApplication-with-patch/EclipseConEurope/something.json\",\"range\":{\"start\":{\"line\":1,\"character\":3},\"end\":{\"line\":1,\"character\":55}}}},\n" + " {\"name\":\"type\",\"kind\":15,\"location\":{\"uri\":\"file:/home/mistria/runtime-EclipseApplication-with-patch/EclipseConEurope/something.json\",\"range\":{\"start\":{\"line\":2,\"character\":3},\"end\":{\"line\":2,\"character\":19}}}},\n" + " {\"name\":\"title\",\"kind\":15,\"location\":{\"uri\":\"file:/home/mistria/runtime-EclipseApplication-with-patch/EclipseConEurope/something.json\",\"range\":{\"start\":{\"line\":3,\"character\":3},\"end\":{\"line\":3,\"character\":50}}}},\n" + " {\"name\":\"additionalProperties\",\"kind\":17,\"location\":{\"uri\":\"file:/home/mistria/runtime-EclipseApplication-with-patch/EclipseConEurope/something.json\",\"range\":{\"start\":{\"line\":4,\"character\":4},\"end\":{\"line\":4,\"character\":32}}}},\n" + " {\"name\":\"properties\",\"kind\":15,\"location\":{\"uri\":\"file:/home/mistria/runtime-EclipseApplication-with-patch/EclipseConEurope/something.json\",\"range\":{\"start\":{\"line\":5,\"character\":3},\"end\":{\"line\":5,\"character\":20}}}}\n" + "]}"); List<? extends Entry> result = (List<? extends Entry>) ((ResponseMessage)message).getResult(); Assert.assertEquals(5, result.size()); for (Entry e : result) { Assert.assertTrue(e.location.uri, e.location.uri.startsWith("file:/home/mistria")); } }
@SuppressWarnings({ "unchecked" }) @Test public void testParseList_02() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Set<Entry>>() {}.getType(), new TypeToken<Set<Entry>>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id)->"foo"); Message message = handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + " \"result\": [\n" + " {\"name\":\"$schema\",\"kind\":15,\"location\":{\"uri\":\"file:/home/mistria/runtime-EclipseApplication-with-patch/EclipseConEurope/something.json\",\"range\":{\"start\":{\"line\":1,\"character\":3},\"end\":{\"line\":1,\"character\":55}}}},\n" + " {\"name\":\"type\",\"kind\":15,\"location\":{\"uri\":\"file:/home/mistria/runtime-EclipseApplication-with-patch/EclipseConEurope/something.json\",\"range\":{\"start\":{\"line\":2,\"character\":3},\"end\":{\"line\":2,\"character\":19}}}},\n" + " {\"name\":\"title\",\"kind\":15,\"location\":{\"uri\":\"file:/home/mistria/runtime-EclipseApplication-with-patch/EclipseConEurope/something.json\",\"range\":{\"start\":{\"line\":3,\"character\":3},\"end\":{\"line\":3,\"character\":50}}}},\n" + " {\"name\":\"additionalProperties\",\"kind\":17,\"location\":{\"uri\":\"file:/home/mistria/runtime-EclipseApplication-with-patch/EclipseConEurope/something.json\",\"range\":{\"start\":{\"line\":4,\"character\":4},\"end\":{\"line\":4,\"character\":32}}}},\n" + " {\"name\":\"properties\",\"kind\":15,\"location\":{\"uri\":\"file:/home/mistria/runtime-EclipseApplication-with-patch/EclipseConEurope/something.json\",\"range\":{\"start\":{\"line\":5,\"character\":3},\"end\":{\"line\":5,\"character\":20}}}}\n" + "]}"); Set<Entry> result = (Set<Entry>) ((ResponseMessage)message).getResult(); Assert.assertEquals(5, result.size()); for (Entry e : result) { Assert.assertTrue(e.location.uri, e.location.uri.startsWith("file:/home/mistria")); } }
@SuppressWarnings({ "unchecked" }) @Test public void testEither_02() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Either<MyEnum, Map<String,String>>>() {}.getType(), new TypeToken<Object>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); Message message = handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"result\": 2\n" + "}"); Either<MyEnum, List<Map<String, String>>> result = (Either<MyEnum, List<Map<String,String>>>) ((ResponseMessage)message).getResult(); Assert.assertTrue(result.isLeft()); Assert.assertEquals(MyEnum.B, result.getLeft()); }
@Test public void testParamsParsing_01() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<Location>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"params\": {\"uri\": \"dummy://mymodel.mydsl\"},\n" + "\"method\":\"foo\"\n" + "}"); Assert.assertEquals(Location.class, message.getParams().getClass()); }
@Test public void testParamsParsing_02() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<Location>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"method\":\"foo\",\n" + "\"params\": {\"uri\": \"dummy://mymodel.mydsl\"}\n" + "}"); Assert.assertEquals(Location.class, message.getParams().getClass()); }
@Test public void testParamsParsing_03() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<Location>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"method\":\"bar\",\n" + "\"params\": {\"uri\": \"dummy://mymodel.mydsl\"}\n" + "}"); Assert.assertEquals(JsonObject.class, message.getParams().getClass()); }
@Test public void testParamsParsing_04() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<Location>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"method\":\"bar\",\n" + "\"params\": null\n" + "}"); Assert.assertEquals(null, message.getParams()); }
@Test public void testRawMultiParamsParsing_01() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<String>() {}.getType(), new TypeToken<Integer>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"method\":\"foo\",\n" + "\"params\": [\"foo\", 2]\n" + "}"); Assert.assertTrue("" + message.getParams().getClass(), message.getParams() instanceof List); List<?> parameters = (List<?>) message.getParams(); Assert.assertEquals(2, parameters.size()); Assert.assertEquals("foo", parameters.get(0)); Assert.assertEquals(2, parameters.get(1)); }
@Test public void testRawMultiParamsParsing_02() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<String>() {}.getType(), new TypeToken<Integer>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"method\":\"bar\",\n" + "\"params\": [\"foo\", 2]\n" + "}"); Assert.assertTrue("" + message.getParams().getClass(), message.getParams() instanceof JsonArray); }
@Test public void testRawMultiParamsParsing_03() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<List<String>>() {}.getType(), new TypeToken<List<Integer>>() {}.getType(), new TypeToken<Location>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"method\":\"foo\",\n" + "\"params\": [[\"foo\", \"bar\"], [1, 2], {\"uri\": \"dummy://mymodel.mydsl\"}]\n" + "}"); Assert.assertTrue("" + message.getParams().getClass(), message.getParams() instanceof List); List<?> parameters = (List<?>) message.getParams(); Assert.assertEquals(3, parameters.size()); Assert.assertEquals("[foo, bar]", parameters.get(0).toString()); Assert.assertEquals("[1, 2]", parameters.get(1).toString()); Assert.assertTrue("" + parameters.get(2).getClass(), parameters.get(2) instanceof Location); }
@Test public void testRawMultiParamsParsing_04() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<List<String>>() {}.getType(), new TypeToken<List<Integer>>() {}.getType(), new TypeToken<Location>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"method\":\"foo\",\n" + "\"params\": [[\"foo\", \"bar\"], [1, 2]]\n" + "}"); Assert.assertTrue("" + message.getParams().getClass(), message.getParams() instanceof List); List<?> parameters = (List<?>) message.getParams(); Assert.assertEquals(3, parameters.size()); Assert.assertEquals("[foo, bar]", parameters.get(0).toString()); Assert.assertEquals("[1, 2]", parameters.get(1).toString()); Assert.assertNull(parameters.get(2)); }
@Test public void testMultiParamsParsing_01() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<String>() {}.getType(), new TypeToken<Integer>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"params\": [\"foo\", 2],\n" + "\"method\":\"foo\"\n" + "}"); Assert.assertTrue("" + message.getParams().getClass(), message.getParams() instanceof List); List<?> parameters = (List<?>) message.getParams(); Assert.assertEquals(2, parameters.size()); Assert.assertEquals("foo", parameters.get(0)); Assert.assertEquals(2, parameters.get(1)); }
@Test public void testMultiParamsParsing_02() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<String>() {}.getType(), new TypeToken<Integer>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"params\": [\"foo\", 2],\n" + "\"method\":\"bar\"\n" + "}"); Assert.assertTrue("" + message.getParams().getClass(), message.getParams() instanceof JsonArray); }
@Test public void testMultiParamsParsing_03() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<List<String>>() {}.getType(), new TypeToken<List<Integer>>() {}.getType(), new TypeToken<Location>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"params\": [[\"foo\", \"bar\"], [1, 2], {\"uri\": \"dummy://mymodel.mydsl\"}],\n" + "\"method\":\"foo\"\n" + "}"); Assert.assertTrue("" + message.getParams().getClass(), message.getParams() instanceof List); List<?> parameters = (List<?>) message.getParams(); Assert.assertEquals(3, parameters.size()); Assert.assertEquals("[foo, bar]", parameters.get(0).toString()); Assert.assertEquals("[1, 2]", parameters.get(1).toString()); Assert.assertTrue("" + parameters.get(2).getClass(), parameters.get(2) instanceof Location); }
@Test public void testMultiParamsParsing_04() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<List<String>>() {}.getType(), new TypeToken<List<Integer>>() {}.getType(), new TypeToken<Location>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"params\": [[\"foo\", \"bar\"], [1, 2]],\n" + "\"method\":\"foo\"\n" + "}"); Assert.assertTrue("" + message.getParams().getClass(), message.getParams() instanceof List); List<?> parameters = (List<?>) message.getParams(); Assert.assertEquals(3, parameters.size()); Assert.assertEquals("[foo, bar]", parameters.get(0).toString()); Assert.assertEquals("[1, 2]", parameters.get(1).toString()); Assert.assertNull(parameters.get(2)); }
@Test public void testEnumParam() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<List<MyEnum>>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); RequestMessage message = (RequestMessage) handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"params\": [1, 2, 3],\n" + "\"method\":\"foo\"\n" + "}"); Assert.assertTrue("" + message.getParams().getClass(), message.getParams() instanceof List); List<?> parameters = (List<?>) message.getParams(); Assert.assertEquals(Arrays.asList(MyEnum.A, MyEnum.B, MyEnum.C), parameters); }
@Test public void testRequest_AllOrders() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<Location>() { }.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); String[] properties = new String[] { "\"jsonrpc\":\"2.0\"", "\"id\":2", "\"method\":\"foo\"", "\"params\": {\"uri\": \"dummy://mymodel.mydsl\"}" }; testAllPermutations(properties, json -> { RequestMessage message = (RequestMessage) handler.parseMessage(json); Object params = message.getParams(); Class<? extends Object> class1 = params.getClass(); Assert.assertEquals(Location.class, class1); Assert.assertEquals("dummy://mymodel.mydsl", ((Location)params).uri); }); }
@Test public void testNormalResponse_AllOrders() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Location>() {}.getType(), new TypeToken<Void>() { }.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); String[] properties = new String[] { "\"jsonrpc\":\"2.0\"", "\"id\":2", "\"result\": {\"uri\": \"dummy://mymodel.mydsl\"}" }; testAllPermutations(properties, json -> { ResponseMessage message = (ResponseMessage) handler.parseMessage(json); Object result = message.getResult(); Class<? extends Object> class1 = result.getClass(); Assert.assertEquals(Location.class, class1); Assert.assertEquals("dummy://mymodel.mydsl", ((Location)result).uri); Assert.assertNull(message.getError()); }); }
@Test public void testErrorResponse_AllOrders() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Location>() {}.getType(), new TypeToken<Void>() { }.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); String[] properties = new String[] { "\"jsonrpc\":\"2.0\"", "\"id\":2", "\"message\": \"failed\"", "\"error\": {\"code\": 123456, \"message\": \"failed\", \"data\": {\"uri\": \"failed\"}}" }; testAllPermutations(properties, json -> { ResponseMessage message = (ResponseMessage) handler.parseMessage(json); Assert.assertEquals("failed", message.getError().getMessage()); Object data = message.getError().getData(); Map<String, String> expected = new HashMap<>(); expected.put("uri", "failed"); Assert.assertEquals(expected, data); Assert.assertNull(message.getResult()); }); }
@Test public void testNotification_AllOrders() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Void>() {}.getType(), new TypeToken<Location>() { }.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); String[] properties = new String[] { "\"jsonrpc\":\"2.0\"", "\"method\":\"foo\"", "\"params\": {\"uri\": \"dummy://mymodel.mydsl\"}" }; testAllPermutations(properties, json -> { NotificationMessage message = (NotificationMessage) handler.parseMessage(json); Object params = message.getParams(); Class<? extends Object> class1 = params.getClass(); Assert.assertEquals(Location.class, class1); Assert.assertEquals("dummy://mymodel.mydsl", ((Location)params).uri); }); }
/** * Create a new Launcher for a given local service object, a given remote interface and an input and output stream. * Threads are started with the given executor service. The wrapper function is applied to the incoming and * outgoing message streams so additional message handling such as validation and tracing can be included. * The {@code configureGson} function can be used to register additional type adapters in the {@link GsonBuilder} * in order to support protocol classes that cannot be handled by Gson's reflective capabilities. * * @param localService - an object on which classes RPC methods are looked up * @param remoteInterface - an interface on which RPC methods are looked up * @param in - inputstream to listen for incoming messages * @param out - outputstream to send outgoing messages * @param executorService - the executor service used to start threads * @param wrapper - a function for plugging in additional message consumers * @param configureGson - a function for Gson configuration */ static <T> DebugLauncher<T> createIoLauncher(Object localService, Class<T> remoteInterface, InputStream in, OutputStream out, ExecutorService executorService, Function<MessageConsumer, MessageConsumer> wrapper, Consumer<GsonBuilder> configureGson) { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<String, JsonRpcMethod>(); supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(remoteInterface)); if (localService instanceof JsonRpcMethodProvider) { JsonRpcMethodProvider rpcMethodProvider = (JsonRpcMethodProvider) localService; supportedMethods.putAll(rpcMethodProvider.supportedMethods()); } else { supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(localService.getClass())); } MessageJsonHandler jsonHandler = new DebugMessageJsonHandler(supportedMethods, configureGson); MessageConsumer outGoingMessageStream = new StreamMessageConsumer(out, jsonHandler); outGoingMessageStream = wrapper.apply(outGoingMessageStream); RemoteEndpoint serverEndpoint = new RemoteEndpoint(outGoingMessageStream, ServiceEndpoints.toEndpoint(localService)); jsonHandler.setMethodProvider(serverEndpoint); // wrap incoming message stream MessageConsumer messageConsumer = wrapper.apply(serverEndpoint); StreamMessageProducer reader = new StreamMessageProducer(in, jsonHandler); T remoteProxy = ServiceEndpoints.toServiceObject(serverEndpoint, remoteInterface); return new DebugLauncher<T> () { @Override public Future<?> startListening() { return ConcurrentMessageProcessor.startProcessing(reader, messageConsumer, executorService); } @Override public T getRemoteProxy() { return remoteProxy; } }; }
/** * Create a new Launcher for a given local service object, a given remote interface and an input and output stream. * Threads are started with the given executor service. The wrapper function is applied to the incoming and * outgoing message streams so additional message handling such as validation and tracing can be included. * The {@code configureGson} function can be used to register additional type adapters in the {@link GsonBuilder} * in order to support protocol classes that cannot be handled by Gson's reflective capabilities. * * @param localService - an object on which classes RPC methods are looked up * @param remoteInterface - an interface on which RPC methods are looked up * @param in - inputstream to listen for incoming messages * @param out - outputstream to send outgoing messages * @param executorService - the executor service used to start threads * @param wrapper - a function for plugging in additional message consumers * @param configureGson - a function for Gson configuration */ static <T> Launcher<T> createIoLauncher(Object localService, Class<T> remoteInterface, InputStream in, OutputStream out, ExecutorService executorService, Function<MessageConsumer, MessageConsumer> wrapper, Consumer<GsonBuilder> configureGson) { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<String, JsonRpcMethod>(); supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(remoteInterface)); if (localService instanceof JsonRpcMethodProvider) { JsonRpcMethodProvider rpcMethodProvider = (JsonRpcMethodProvider) localService; supportedMethods.putAll(rpcMethodProvider.supportedMethods()); } else { supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(localService.getClass())); } MessageJsonHandler jsonHandler = new MessageJsonHandler(supportedMethods, configureGson); MessageConsumer outGoingMessageStream = new StreamMessageConsumer(out, jsonHandler); outGoingMessageStream = wrapper.apply(outGoingMessageStream); RemoteEndpoint serverEndpoint = new RemoteEndpoint(outGoingMessageStream, ServiceEndpoints.toEndpoint(localService)); jsonHandler.setMethodProvider(serverEndpoint); // wrap incoming message stream MessageConsumer messageConsumer = wrapper.apply(serverEndpoint); StreamMessageProducer reader = new StreamMessageProducer(in, jsonHandler); T remoteProxy = ServiceEndpoints.toServiceObject(serverEndpoint, remoteInterface); return new Launcher<T> () { @Override public Future<?> startListening() { return ConcurrentMessageProcessor.startProcessing(reader, messageConsumer, executorService); } @Override public T getRemoteProxy() { return remoteProxy; } }; }
@Before public void setup() { final Map<String, JsonRpcMethod> methods = ServiceEndpoints.getSupportedMethods(LanguageServer.class); this.jsonHandler = new MessageJsonHandler(methods) { @Override public GsonBuilder getDefaultGsonBuilder() { return super.getDefaultGsonBuilder().setPrettyPrinting(); } }; }
@Before public void setup() { final Map<String, JsonRpcMethod> methods = ServiceEndpoints.getSupportedMethods(LanguageServer.class); final Map<String, JsonRpcMethod> clientMethods = ServiceEndpoints.getSupportedMethods(LanguageClient.class); final HashMap<String, JsonRpcMethod> all = new HashMap<String, JsonRpcMethod>(); all.putAll(methods); all.putAll(clientMethods); MessageJsonHandler _messageJsonHandler = new MessageJsonHandler(all); this.jsonHandler = _messageJsonHandler; }
/** * Create a new Launcher for a given local service object, a given remote * interface and an input and output stream. Threads are started with the given * executor service. The wrapper function is applied to the incoming and * outgoing message streams so additional message handling such as validation * and tracing can be included. The {@code configureGson} function can be used * to register additional type adapters in the {@link GsonBuilder} in order to * support protocol classes that cannot be handled by Gson's reflective * capabilities. * * @param localService * - an object on which classes RPC methods are looked up * @param remoteInterface * - an interface on which RPC methods are looked up * @param in * - inputstream to listen for incoming messages * @param out * - outputstream to send outgoing messages * @param executorService * - the executor service used to start threads * @param wrapper * - a function for plugging in additional message consumers * @param configureGson * - a function for Gson configuration */ static <T> DebugLauncher<T> createIoLauncher(Object localService, Class<T> remoteInterface, InputStream in, OutputStream out, ExecutorService executorService, Function<MessageConsumer, MessageConsumer> wrapper, Consumer<GsonBuilder> configureGson) { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<String, JsonRpcMethod>(); supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(remoteInterface)); if (localService instanceof JsonRpcMethodProvider) { JsonRpcMethodProvider rpcMethodProvider = (JsonRpcMethodProvider) localService; supportedMethods.putAll(rpcMethodProvider.supportedMethods()); } else { supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(localService.getClass())); } MessageJsonHandler jsonHandler = new DebugMessageJsonHandler(supportedMethods, configureGson); MessageConsumer outGoingMessageStream = new StreamMessageConsumer(out, jsonHandler); outGoingMessageStream = wrapper.apply(outGoingMessageStream); RemoteEndpoint serverEndpoint = new DebugRemoteEndpoint(outGoingMessageStream, ServiceEndpoints.toEndpoint(localService)); jsonHandler.setMethodProvider(serverEndpoint); // wrap incoming message stream MessageConsumer messageConsumer = wrapper.apply(serverEndpoint); StreamMessageProducer reader = new StreamMessageProducer(in, jsonHandler); T remoteProxy = ServiceEndpoints.toServiceObject(serverEndpoint, remoteInterface); return new DebugLauncher<T>() { @Override public Future<?> startListening() { return ConcurrentMessageProcessor.startProcessing(reader, messageConsumer, executorService); } @Override public T getRemoteProxy() { return remoteProxy; } }; }
@SuppressWarnings({ "unchecked" }) @Test public void testEither_01() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Either<String, List<Map<String,String>>>>() {}.getType(), new TypeToken<Either<String, Integer>>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); Message message = handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + " \"result\": [\n" + " {\"name\":\"foo\"},\n" + " {\"name\":\"bar\"}\n" + "]}"); Either<String, List<Map<String, String>>> result = (Either<String, List<Map<String,String>>>) ((ResponseMessage)message).getResult(); Assert.assertTrue(result.isRight()); for (Map<String, String> e : result.getRight()) { Assert.assertNotNull(e.get("name")); } message = handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"result\": \"name\"\n" + "}"); result = (Either<String, List<Map<String,String>>>) ((ResponseMessage)message).getResult(); Assert.assertFalse(result.isRight()); Assert.assertEquals("name",result.getLeft()); }
@SuppressWarnings({ "unchecked" }) @Test public void testEither_04() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Either<MyClass, List<? extends MyClass>>>() {}.getType(), new TypeToken<Object>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); Message message = handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"result\": {\n" + " value:\"foo\"\n" + "}}"); Either<MyClass, List<? extends MyClass>> result = (Either<MyClass, List<? extends MyClass>>) ((ResponseMessage)message).getResult(); Assert.assertTrue(result.isLeft()); Assert.assertEquals("foo", result.getLeft().getValue()); message = handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"result\": [{\n" + " value:\"bar\"\n" + "}]}"); result = (Either<MyClass, List<? extends MyClass>>) ((ResponseMessage)message).getResult(); Assert.assertTrue(result.isRight()); Assert.assertEquals("bar", result.getRight().get(0).getValue()); }
@SuppressWarnings({ "unchecked" }) @Test public void testEither_05() { Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>(); supportedMethods.put("foo", JsonRpcMethod.request("foo", new TypeToken<Either<List<MyClass>, MyClassList>>() {}.getType(), new TypeToken<Object>() {}.getType())); MessageJsonHandler handler = new MessageJsonHandler(supportedMethods); handler.setMethodProvider((id) -> "foo"); Message message = handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"result\": [{\n" + " value:\"foo\"\n" + "}]}"); Either<List<MyClass>, MyClassList> result = (Either<List<MyClass>, MyClassList>) ((ResponseMessage)message).getResult(); Assert.assertTrue(result.isLeft()); Assert.assertEquals("foo", result.getLeft().get(0).getValue()); message = handler.parseMessage("{\"jsonrpc\":\"2.0\"," + "\"id\":\"2\",\n" + "\"result\": {\n" + " items: [{\n" + " value:\"bar\"\n" + "}]}}"); result = (Either<List<MyClass>, MyClassList>) ((ResponseMessage)message).getResult(); Assert.assertTrue(result.isRight()); Assert.assertEquals("bar", result.getRight().getItems().get(0).getValue()); }
public DebugMessageTypeAdapterFactory(MessageJsonHandler handler) { this.handler = handler; }
Adapter(MessageJsonHandler handler, Gson gson) { this.handler = handler; this.gson = gson; }
public Factory(MessageJsonHandler handler) { this.handler = handler; }
public MessageTypeAdapter(MessageJsonHandler handler, Gson gson) { this.handler = handler; this.gson = gson; }
public MessageTypeAdapterFactory(MessageJsonHandler handler) { super(handler); }
@Override public String toString() { return MessageJsonHandler.toString(this); }