@Override public LanguageServer get(LanguageClient client, InputStream in, OutputStream out) { Launcher<LanguageServer> launcher = createLauncher(client, LanguageServer.class, in, out); LOG.debug("Created launcher for language server"); launcher.startListening(); LOG.debug("Started listening"); LanguageServer remoteProxy = launcher.getRemoteProxy(); LOG.debug("Got remote proxy"); return remoteProxy; }
@Test public void testDone() throws Exception { A a = new A() { @Override public void say(Param p) { } }; Launcher<A> launcher = Launcher.createLauncher(a, A.class, new ByteArrayInputStream("".getBytes()), new ByteArrayOutputStream()); Future<?> startListening = launcher.startListening(); startListening.get(TIMEOUT, TimeUnit.MILLISECONDS); Assert.assertTrue(startListening.isDone()); Assert.assertFalse(startListening.isCancelled()); }
private Future<Void> runAsync(Connection connection) throws Exception { LanguageServer server = this.languageServer; ExecutorService executor = createServerThreads(); Function<MessageConsumer, MessageConsumer> wrapper = (MessageConsumer consumer) -> { return (msg) -> { try { consumer.consume(msg); } catch (UnsupportedOperationException e) { //log a warning and ignore. We are getting some messages from vsCode the server doesn't know about log.warn("Unsupported message was ignored!", e); } }; }; Launcher<STS4LanguageClient> launcher = Launcher.createLauncher(server, STS4LanguageClient.class, connection.in, connection.out, executor, wrapper ); if (server instanceof LanguageClientAware) { LanguageClient client = launcher.getRemoteProxy(); ((LanguageClientAware) server).connect(client); } return launcher.startListening(); }
/** * creates a proxy, delegating to a remote endpoint, forwarding to another remote endpoint, that delegates to an actual implementation. * @param intf * @param impl * @return * @throws IOException */ public <T> T wrap(Class<T> intf, T impl) { PipedInputStream in1 = new PipedInputStream(); PipedOutputStream out1 = new PipedOutputStream(); Launcher<T> launcher1 = Launcher.createLauncher(impl, intf, in1, out1); PipedInputStream in2 = new PipedInputStream(); PipedOutputStream out2 = new PipedOutputStream(); Launcher<T> launcher2 = Launcher.createLauncher(new Object(), intf, in2, out2); try { in1.connect(out2); in2.connect(out1); } catch (IOException e) { throw new IllegalStateException(e); } launcher1.startListening(); launcher2.startListening(); return launcher2.getRemoteProxy(); } }
@Test public void testResponse2() throws Exception { // create client message String requestMessage = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": 42,\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"value\": \"bar\" }\n" + "}"; String clientMessage = getHeader(requestMessage.getBytes().length) + requestMessage; // create server side ByteArrayInputStream in = new ByteArrayInputStream(clientMessage.getBytes()); ByteArrayOutputStream out = new ByteArrayOutputStream(); MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out); serverSideLauncher.startListening().get(TIMEOUT, TimeUnit.MILLISECONDS); Assert.assertEquals("Content-Length: 50" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":42,\"result\":{\"value\":\"bar\"}}", out.toString()); }
@Test public void testEither() throws Exception { // create client message String requestMessage = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": 42,\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"either\": \"bar\", \"value\": \"foo\" }\n" + "}"; String clientMessage = getHeader(requestMessage.getBytes().length) + requestMessage; // create server side ByteArrayInputStream in = new ByteArrayInputStream(clientMessage.getBytes()); ByteArrayOutputStream out = new ByteArrayOutputStream(); MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out); serverSideLauncher.startListening().get(TIMEOUT, TimeUnit.MILLISECONDS); Assert.assertEquals("Content-Length: 65" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":42,\"result\":{\"value\":\"foo\",\"either\":\"bar\"}}", out.toString()); }
@Test public void testResponse1() throws Exception { // create client message String requestMessage = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": \"42\",\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"value\": \"bar\" }\n" + "}"; String clientMessage = getHeader(requestMessage.getBytes().length) + requestMessage; // create server side ByteArrayInputStream in = new ByteArrayInputStream(clientMessage.getBytes()); ByteArrayOutputStream out = new ByteArrayOutputStream(); MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out); serverSideLauncher.startListening().get(TIMEOUT, TimeUnit.MILLISECONDS); Assert.assertEquals("Content-Length: 52" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":\"42\",\"result\":{\"value\":\"bar\"}}", out.toString()); }
@Test public void testEitherNull() throws Exception { // create client message String requestMessage = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": 42,\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"either\": null, \"value\": \"foo\" }\n" + "}"; String clientMessage = getHeader(requestMessage.getBytes().length) + requestMessage; // create server side ByteArrayInputStream in = new ByteArrayInputStream(clientMessage.getBytes()); ByteArrayOutputStream out = new ByteArrayOutputStream(); MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out); serverSideLauncher.startListening().get(TIMEOUT, TimeUnit.MILLISECONDS); Assert.assertEquals("Content-Length: 50" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":42,\"result\":{\"value\":\"foo\"}}", out.toString()); }
@Test public void testValidationIssue2() throws Exception { String requestMessage1 = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": \"1\",\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"value\": null, \"nested\": { \"value\": null } }\n" + "}"; String clientMessages = getHeader(requestMessage1.getBytes().length) + requestMessage1; ByteArrayInputStream in = new ByteArrayInputStream(clientMessages.getBytes()); ByteArrayOutputStream out = new ByteArrayOutputStream(); MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out, true, null); serverSideLauncher.startListening().get(TIMEOUT, TimeUnit.MILLISECONDS); Assert.assertEquals("Content-Length: 379" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"error\":{\"code\":-32600,\"message\":\"Multiple issues were found in \\u0027askServer\\u0027 request.\"," + "\"data\":[" + "{\"text\":\"The accessor \\u0027MyParam.getValue()\\u0027 must return a non-null value. Path: $.params.nested.value\",\"code\":-32602}," + "{\"text\":\"The accessor \\u0027MyParam.getValue()\\u0027 must return a non-null value. Path: $.params.value\",\"code\":-32602}" + "]}}", out.toString()); }
@Test public void testMalformedJson4() throws Exception { String requestMessage1 = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": \"1\",\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"value\": \"bar\" }\n" + "}}"; String requestMessage2 = "{\"jsonrpc\":\"2.0\",\n" + "\"id\":\"2\",\n" + "\"method\":\"askServer\",\n" + "\"params\": { \"value\": \"bar\" }\n" + "}"; String clientMessages = getHeader(requestMessage1.getBytes().length) + requestMessage1 + getHeader(requestMessage2.getBytes().length) + requestMessage2; ByteArrayInputStream in = new ByteArrayInputStream(clientMessages.getBytes()); ByteArrayOutputStream out = new ByteArrayOutputStream(); MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out); serverSideLauncher.startListening().get(TIMEOUT, TimeUnit.MILLISECONDS); Assert.assertEquals("Content-Length: 195" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"error\":{\"code\":-32700,\"message\":\"Message could not be parsed.\"," + "\"data\":{\"message\":\"Use JsonReader.setLenient(true) to accept malformed JSON at line 5 column 3 path $\"}}}" + "Content-Length: 51" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":\"2\",\"result\":{\"value\":\"bar\"}}", out.toString()); }
@Test public void testMalformedJson1() throws Exception { String requestMessage1 = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": \"1\",\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"value\": }\n" + "}"; String requestMessage2 = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": \"2\",\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"value\": \"bar\" }\n" + "}"; String clientMessages = getHeader(requestMessage1.getBytes().length) + requestMessage1 + getHeader(requestMessage2.getBytes().length) + requestMessage2; ByteArrayInputStream in = new ByteArrayInputStream(clientMessages.getBytes()); ByteArrayOutputStream out = new ByteArrayOutputStream(); MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out); serverSideLauncher.startListening().get(TIMEOUT, TimeUnit.MILLISECONDS); Assert.assertEquals("Content-Length: 214" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"error\":{\"code\":-32700,\"message\":\"Message could not be parsed.\"," + "\"data\":{\"message\":\"com.google.gson.stream.MalformedJsonException: Expected value at line 4 column 22 path $.params.value\"}}}" + "Content-Length: 51" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":\"2\",\"result\":{\"value\":\"bar\"}}", out.toString()); }
@Test public void testCanceled() throws Exception { A a = new A() { @Override public void say(Param p) { } }; Launcher<A> launcher = Launcher.createLauncher(a, A.class, new InputStream() { @Override public int read() throws IOException { try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } return '\n'; } }, new ByteArrayOutputStream()); Future<?> startListening = launcher.startListening(); startListening.cancel(true); Assert.assertTrue(startListening.isDone()); Assert.assertTrue(startListening.isCancelled()); }
@Test public void testMalformedJson3() throws Exception { String requestMessage1 = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": \"1\",\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"value\": \"bar\" }\n" + "]"; String requestMessage2 = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": \"2\",\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"value\": \"bar\" }\n" + "}"; String clientMessages = getHeader(requestMessage1.getBytes().length) + requestMessage1 + getHeader(requestMessage2.getBytes().length) + requestMessage2; ByteArrayInputStream in = new ByteArrayInputStream(clientMessages.getBytes()); ByteArrayOutputStream out = new ByteArrayOutputStream(); MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out); serverSideLauncher.startListening().get(TIMEOUT, TimeUnit.MILLISECONDS); Assert.assertEquals("Content-Length: 165" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"error\":{\"code\":-32700,\"message\":\"Message could not be parsed.\"," + "\"data\":{\"message\":\"Unterminated object at line 5 column 2 path $.params\"}}}" + "Content-Length: 51" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":\"2\",\"result\":{\"value\":\"bar\"}}", out.toString()); }
@Test public void testValidationIssue1() throws Exception { String requestMessage1 = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": \"1\",\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"value\": null }\n" + "}"; String requestMessage2 = "{\"jsonrpc\": \"2.0\",\n" + "\"id\": \"2\",\n" + "\"method\": \"askServer\",\n" + "\"params\": { \"value\": \"bar\" }\n" + "}"; String clientMessages = getHeader(requestMessage1.getBytes().length) + requestMessage1 + getHeader(requestMessage2.getBytes().length) + requestMessage2; ByteArrayInputStream in = new ByteArrayInputStream(clientMessages.getBytes()); ByteArrayOutputStream out = new ByteArrayOutputStream(); MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out, true, null); serverSideLauncher.startListening().get(TIMEOUT, TimeUnit.MILLISECONDS); Assert.assertEquals("Content-Length: 157" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":\"1\",\"error\":{\"code\":-32602,\"message\":\"The accessor \\u0027MyParam.getValue()\\u0027 must return a non-null value. Path: $.params.value\"}}" + "Content-Length: 51" + CRLF + CRLF + "{\"jsonrpc\":\"2.0\",\"id\":\"2\",\"result\":{\"value\":\"bar\"}}", out.toString()); }
private void startConnection() throws IOException { Launcher<JavaLanguageClient> launcher; ExecutorService executorService = Executors.newCachedThreadPool(); protocol = new JDTLanguageServer(projectsManager, preferenceManager); if (JDTEnvironmentUtils.inSocketStreamDebugMode()) { String host = JDTEnvironmentUtils.getClientHost(); Integer port = JDTEnvironmentUtils.getClientPort(); InetSocketAddress inetSocketAddress = new InetSocketAddress(host, port); AsynchronousServerSocketChannel serverSocket = AsynchronousServerSocketChannel.open().bind(inetSocketAddress); try { AsynchronousSocketChannel socketChannel = serverSocket.accept().get(); InputStream in = Channels.newInputStream(socketChannel); OutputStream out = Channels.newOutputStream(socketChannel); Function<MessageConsumer, MessageConsumer> messageConsumer = it -> it; launcher = Launcher.createIoLauncher(protocol, JavaLanguageClient.class, in, out, executorService, messageConsumer); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException("Error when opening a socket channel at " + host + ":" + port + ".", e); } } else { ConnectionStreamFactory connectionFactory = new ConnectionStreamFactory(); InputStream in = connectionFactory.getInputStream(); OutputStream out = connectionFactory.getOutputStream(); Function<MessageConsumer, MessageConsumer> wrapper = new ParentProcessWatcher(this.languageServer); launcher = Launcher.createLauncher(protocol, JavaLanguageClient.class, in, out, executorService, wrapper); } protocol.connectClient(launcher.getRemoteProxy()); launcher.startListening(); }
Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out); serverSideLauncher.startListening();
@Test public void testBothDirectionRequests() throws Exception { // create client side PipedInputStream in = new PipedInputStream(); PipedOutputStream out = new PipedOutputStream(); PipedInputStream in2 = new PipedInputStream(); PipedOutputStream out2 = new PipedOutputStream(); in.connect(out2); out.connect(in2); MyClient client = new MyClientImpl(); Launcher<MyServer> clientSideLauncher = Launcher.createLauncher(client, MyServer.class, in, out); // create server side MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in2, out2); clientSideLauncher.startListening(); serverSideLauncher.startListening(); CompletableFuture<MyParam> fooFuture = clientSideLauncher.getRemoteProxy().askServer(new MyParam("FOO")); CompletableFuture<MyParam> barFuture = serverSideLauncher.getRemoteProxy().askClient(new MyParam("BAR")); Assert.assertEquals("FOO", fooFuture.get(TIMEOUT, TimeUnit.MILLISECONDS).value); Assert.assertEquals("BAR", barFuture.get(TIMEOUT, TimeUnit.MILLISECONDS).value); }
ByteArrayOutputStream out = new ByteArrayOutputStream(); MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out); serverSideLauncher.startListening();
ByteArrayOutputStream out = new ByteArrayOutputStream(); MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in, out); serverSideLauncher.startListening();
Launcher<MyServer> clientSideLauncher = Launcher.createLauncher(client, MyServer.class, in, out);