diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/CloseableLifeCycle.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/CloseableLifeCycle.java new file mode 100644 index 00000000000..4a2a2b31b73 --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/CloseableLifeCycle.java @@ -0,0 +1,41 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.util.component; + +public final class CloseableLifeCycle implements AutoCloseable +{ + public T lifecycle; + + public CloseableLifeCycle(T lifecycle) throws Exception + { + this.lifecycle = lifecycle; + this.lifecycle.start(); + } + + public T get() + { + return lifecycle; + } + + @Override + public void close() throws Exception + { + lifecycle.stop(); + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java index ba9710a7e3b..399dc5e5edd 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java @@ -47,7 +47,6 @@ import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.function.CommonEndpointFunctions; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.UnorderedSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; import org.eclipse.jetty.websocket.jsr356.JsrSession; import org.eclipse.jetty.websocket.jsr356.decoders.AvailableDecoders; @@ -420,7 +419,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions } } - argBuilder.addSignature(new UnorderedSignature(callArgs)); + argBuilder.addSignature(callArgs); return argBuilder; } diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnByteArrayFunction.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnByteArrayFunction.java index b746f41a1ae..a6006082193 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnByteArrayFunction.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnByteArrayFunction.java @@ -27,7 +27,6 @@ import javax.websocket.Session; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.UnorderedSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -80,7 +79,7 @@ public class JsrOnByteArrayFunction implements Function callArgs[idx++] = arg; } - argBuilder.addSignature(new UnorderedSignature(callArgs)); + argBuilder.addSignature(callArgs); // Attempt to build callable this.callable = argBuilder.build(method); diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnByteBufferFunction.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnByteBufferFunction.java index ba53586eabe..657b20495ba 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnByteBufferFunction.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnByteBufferFunction.java @@ -28,7 +28,6 @@ import javax.websocket.Session; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.UnorderedSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -77,7 +76,7 @@ public class JsrOnByteBufferFunction implements Function callArgs[idx++] = arg; } - argBuilder.addSignature(new UnorderedSignature(callArgs)); + argBuilder.addSignature(callArgs); // Attempt to build callable this.callable = argBuilder.build(method); diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnInputStreamFunction.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnInputStreamFunction.java index f7dc1e9508c..a8762c4239c 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnInputStreamFunction.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrOnInputStreamFunction.java @@ -28,7 +28,6 @@ import javax.websocket.Session; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.UnorderedSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -78,7 +77,7 @@ public class JsrOnInputStreamFunction implements Function callArgs[idx++] = arg; } - argBuilder.addSignature(new UnorderedSignature(callArgs)); + argBuilder.addSignature(callArgs); // Attempt to build callable this.callable = argBuilder.build(method, callArgs); diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTrackingTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTrackingTest.java index ca0cd2b00f5..47217fd70c7 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTrackingTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/SessionTrackingTest.java @@ -18,8 +18,11 @@ package org.eclipse.jetty.websocket.jsr356.server; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + import java.net.URI; -import java.util.Set; +import java.util.Collection; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -33,129 +36,22 @@ import javax.websocket.server.ServerEndpoint; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.eclipse.jetty.util.StringUtil; import org.eclipse.jetty.websocket.common.WebSocketSession; import org.eclipse.jetty.websocket.jsr356.ClientContainer; import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer; import org.eclipse.jetty.websocket.server.WebSocketServerFactory; -import org.hamcrest.Matchers; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; public class SessionTrackingTest { - private Server server; - private ServerContainer serverContainer; - private WebSocketServerFactory wsServerFactory; - private URI serverURI; - - @Before - public void startServer() throws Exception + public static class ClientSocket extends Endpoint { - QueuedThreadPool serverThreads = new QueuedThreadPool(); - serverThreads.setName("server"); - server = new Server(serverThreads); - ServerConnector serverConnector = new ServerConnector(server); - serverConnector.setPort(0); - server.addConnector(serverConnector); - ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS); - servletContextHandler.setContextPath("/"); - server.setHandler(servletContextHandler); - - serverContainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler); - serverContainer.addEndpoint(EchoSocket.class); - - wsServerFactory = serverContainer.getBean(WebSocketServerFactory.class); - - server.start(); - - serverURI = new URI("ws://localhost:" + serverConnector.getLocalPort()); - } - - @After - public void stopServer() throws Exception - { - if (server != null) - server.stop(); - } - - @Test - public void testAddRemoveSessions() throws Exception - { - // Create Client - ClientContainer clientContainer = new ClientContainer(); - QueuedThreadPool clientThreads = new QueuedThreadPool(); - clientThreads.setName("client"); - clientContainer.getClient().setExecutor(clientThreads); - try - { - CountDownLatch openedLatch = new CountDownLatch(2); - CountDownLatch closedLatch = new CountDownLatch(2); - wsServerFactory.addSessionListener(new WebSocketSession.Listener() - { - @Override - public void onOpened(WebSocketSession session) - { - openedLatch.countDown(); - } - - @Override - public void onClosed(WebSocketSession session) - { - closedLatch.countDown(); - } - }); - - clientContainer.start(); - - // Establish connections - ClientSocket cli1 = new ClientSocket(); - clientContainer.connectToServer(cli1, serverURI.resolve("/test")); - cli1.waitForOpen(1, TimeUnit.SECONDS); - - // Establish new connection - ClientSocket cli2 = new ClientSocket(); - clientContainer.connectToServer(cli2, serverURI.resolve("/test")); - cli2.waitForOpen(1, TimeUnit.SECONDS); - - openedLatch.await(5, TimeUnit.SECONDS); - assertServerOpenConnectionCount(2); - - // Establish close both connections - cli1.session.close(); - cli2.session.close(); - - cli1.waitForClose(1, TimeUnit.SECONDS); - cli2.waitForClose(1, TimeUnit.SECONDS); - - closedLatch.await(5, TimeUnit.SECONDS); - assertServerOpenConnectionCount(0); - } - finally - { - clientContainer.stop(); - } - } - - private void assertServerOpenConnectionCount(int expectedCount) - { - Set sessions = serverContainer.getOpenSessions(); - int openCount = 0; - for (Session session : sessions) - { - Assert.assertThat("Session.isopen: " + session, session.isOpen(), Matchers.is(true)); - openCount++; - } - Assert.assertThat("Open Session Count", openCount, Matchers.is(expectedCount)); - } - - private static class ClientSocket extends Endpoint - { - private Session session; - private CountDownLatch openLatch = new CountDownLatch(1); - private CountDownLatch closeLatch = new CountDownLatch(1); + public Session session; + public CountDownLatch openLatch = new CountDownLatch(1); + public CountDownLatch closeLatch = new CountDownLatch(1); @Override public void onOpen(Session session, EndpointConfig config) @@ -172,12 +68,12 @@ public class SessionTrackingTest public void waitForOpen(long timeout, TimeUnit unit) throws InterruptedException { - Assert.assertThat("ClientSocket opened", openLatch.await(timeout, unit), Matchers.is(true)); + assertThat("ClientSocket opened",openLatch.await(timeout,unit),is(true)); } public void waitForClose(long timeout, TimeUnit unit) throws InterruptedException { - Assert.assertThat("ClientSocket opened", closeLatch.await(timeout, unit), Matchers.is(true)); + assertThat("ClientSocket opened",closeLatch.await(timeout,unit),is(true)); } } @@ -190,4 +86,98 @@ public class SessionTrackingTest return msg; } } + + private static Server server; + private static WebSocketServerFactory wsServerFactory; + private static URI serverURI; + + @BeforeClass + public static void startServer() throws Exception + { + Server server = new Server(); + ServerConnector serverConnector = new ServerConnector(server); + serverConnector.setPort(0); + server.addConnector(serverConnector); + ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS); + servletContextHandler.setContextPath("/"); + server.setHandler(servletContextHandler); + + ServerContainer serverContainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler); + serverContainer.addEndpoint(EchoSocket.class); + + wsServerFactory = serverContainer.getBean(WebSocketServerFactory.class); + + server.start(); + + String host = serverConnector.getHost(); + if (StringUtil.isBlank(host)) + { + host = "localhost"; + } + serverURI = new URI("ws://" + host + ":" + serverConnector.getLocalPort()); + } + + @AfterClass + public static void stopServer() throws Exception + { + if (server == null) + { + return; + } + + server.stop(); + } + + @Test + public void testAddRemoveSessions() throws Exception + { + // Create Client + ClientContainer clientContainer = new ClientContainer(); + try + { + clientContainer.start(); + + // Establish connections + ClientSocket cli1 = new ClientSocket(); + clientContainer.connectToServer(cli1,serverURI.resolve("/test")); + cli1.waitForOpen(1,TimeUnit.SECONDS); + + // Assert open connections + assertServerOpenConnectionCount(1); + + // Establish new connection + ClientSocket cli2 = new ClientSocket(); + clientContainer.connectToServer(cli2,serverURI.resolve("/test")); + cli2.waitForOpen(1,TimeUnit.SECONDS); + + // Assert open connections + assertServerOpenConnectionCount(2); + + // Establish close both connections + cli1.session.close(); + cli2.session.close(); + + cli1.waitForClose(1,TimeUnit.SECONDS); + cli2.waitForClose(1,TimeUnit.SECONDS); + + // Assert open connections + assertServerOpenConnectionCount(0); + } + finally + { + clientContainer.stop(); + } + } + + private void assertServerOpenConnectionCount(int expectedCount) + { + Collection sessions = wsServerFactory.getBeans(javax.websocket.Session.class); + int openCount = 0; + for (javax.websocket.Session session : sessions) + { + assertThat("Session.isopen: " + session,session.isOpen(),is(true)); + openCount++; + } + assertThat("Open Session Count",openCount,is(expectedCount)); + } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnByteArrayFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnByteArrayFunction.java index 9b37886d103..1e8123e1311 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnByteArrayFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnByteArrayFunction.java @@ -27,7 +27,6 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.ExactSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -37,17 +36,14 @@ public class OnByteArrayFunction implements Function { private static final DynamicArgs.Builder ARGBUILDER; private static final Arg ARG_SESSION = new Arg(1, Session.class); - private static final Arg ARG_BUFFER = new Arg(2, byte[].class); + private static final Arg ARG_BUFFER = new Arg(2, byte[].class).required(); private static final Arg ARG_OFFSET = new Arg(3, int.class); private static final Arg ARG_LENGTH = new Arg(4, int.class); static { ARGBUILDER = new DynamicArgs.Builder(); - ARGBUILDER.addSignature(new ExactSignature(ARG_BUFFER)); - ARGBUILDER.addSignature(new ExactSignature(ARG_BUFFER, ARG_OFFSET, ARG_LENGTH)); - ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_BUFFER)); - ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_BUFFER, ARG_OFFSET, ARG_LENGTH)); + ARGBUILDER.addSignature(ARG_SESSION, ARG_BUFFER, ARG_OFFSET, ARG_LENGTH); } public static DynamicArgs.Builder getDynamicArgsBuilder() diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnByteBufferFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnByteBufferFunction.java index 730bfceaccb..264f8814383 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnByteBufferFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnByteBufferFunction.java @@ -28,7 +28,6 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.ExactSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -38,13 +37,12 @@ public class OnByteBufferFunction implements Function { private static final DynamicArgs.Builder ARGBUILDER; private static final Arg ARG_SESSION = new Arg(1, Session.class); - private static final Arg ARG_BUFFER = new Arg(2, ByteBuffer.class); + private static final Arg ARG_BUFFER = new Arg(2, ByteBuffer.class).required(); static { ARGBUILDER = new DynamicArgs.Builder(); - ARGBUILDER.addSignature(new ExactSignature(ARG_BUFFER)); - ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_BUFFER)); + ARGBUILDER.addSignature(ARG_SESSION, ARG_BUFFER); } public static DynamicArgs.Builder getDynamicArgsBuilder() diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnCloseFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnCloseFunction.java index 4c869c5d2c8..e836f09473f 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnCloseFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnCloseFunction.java @@ -28,7 +28,6 @@ import org.eclipse.jetty.websocket.common.CloseInfo; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.ExactSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -44,10 +43,7 @@ public class OnCloseFunction implements Function static { ARGBUILDER = new DynamicArgs.Builder(); - ARGBUILDER.addSignature(new ExactSignature()); - ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION)); - ARGBUILDER.addSignature(new ExactSignature(ARG_STATUS_CODE, ARG_REASON)); - ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_STATUS_CODE, ARG_REASON)); + ARGBUILDER.addSignature(ARG_SESSION, ARG_STATUS_CODE, ARG_REASON); } private final Session session; diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnErrorFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnErrorFunction.java index 3505223444e..0f5e8934d1d 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnErrorFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnErrorFunction.java @@ -27,7 +27,6 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.ExactSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -37,13 +36,12 @@ public class OnErrorFunction implements Function { private static final DynamicArgs.Builder ARGBUILDER; private static final Arg ARG_SESSION = new Arg(1, Session.class); - private static final Arg ARG_CAUSE = new Arg(2, Throwable.class); + private static final Arg ARG_CAUSE = new Arg(2, Throwable.class).required(); static { ARGBUILDER = new DynamicArgs.Builder(); - ARGBUILDER.addSignature(new ExactSignature(ARG_CAUSE)); - ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_CAUSE)); + ARGBUILDER.addSignature(ARG_SESSION, ARG_CAUSE); } private final Session session; diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnFrameFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnFrameFunction.java index 1005d83f3ad..225f932e7d8 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnFrameFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnFrameFunction.java @@ -29,7 +29,6 @@ import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.WebSocketFrame; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.ExactSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -39,13 +38,12 @@ public class OnFrameFunction implements Function { private static final DynamicArgs.Builder ARGBUILDER; private static final Arg ARG_SESSION = new Arg(1, Session.class); - private static final Arg ARG_FRAME = new Arg(2, Frame.class); + private static final Arg ARG_FRAME = new Arg(2, Frame.class).required(); static { ARGBUILDER = new DynamicArgs.Builder(); - ARGBUILDER.addSignature(new ExactSignature(ARG_FRAME)); - ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_FRAME)); + ARGBUILDER.addSignature(ARG_SESSION, ARG_FRAME); } private final Session session; diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnInputStreamFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnInputStreamFunction.java index ab6abef4675..302b55cde80 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnInputStreamFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnInputStreamFunction.java @@ -28,7 +28,6 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.ExactSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -39,13 +38,12 @@ public class OnInputStreamFunction implements Function { private static final DynamicArgs.Builder ARGBUILDER; private static final Arg ARG_SESSION = new Arg(1, Session.class); - private static final Arg ARG_STREAM = new Arg(2, InputStream.class); + private static final Arg ARG_STREAM = new Arg(2, InputStream.class).required(); static { ARGBUILDER = new DynamicArgs.Builder(); - ARGBUILDER.addSignature(new ExactSignature(ARG_STREAM)); - ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_STREAM)); + ARGBUILDER.addSignature(ARG_SESSION, ARG_STREAM); } public static DynamicArgs.Builder getDynamicArgsBuilder() diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnOpenFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnOpenFunction.java index bcdc1056ceb..00c1c6d952a 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnOpenFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnOpenFunction.java @@ -27,7 +27,6 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.ExactSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -36,13 +35,12 @@ import org.eclipse.jetty.websocket.common.util.ReflectUtils; public class OnOpenFunction implements Function { private static final DynamicArgs.Builder ARGBUILDER; - private static final Arg ARG_SESSION = new Arg(1, Session.class); + private static final Arg ARG_SESSION = new Arg(1, Session.class).required(); static { ARGBUILDER = new DynamicArgs.Builder(); - ARGBUILDER.addSignature(new ExactSignature()); - ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION)); + ARGBUILDER.addSignature(ARG_SESSION); } private final Object endpoint; diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnReaderFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnReaderFunction.java index fff69b300f0..40cd87a16aa 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnReaderFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnReaderFunction.java @@ -20,15 +20,17 @@ package org.eclipse.jetty.websocket.common.function; import java.io.Reader; import java.lang.reflect.Method; +import java.util.Objects; import java.util.function.Function; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.ExactSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -36,15 +38,15 @@ import org.eclipse.jetty.websocket.common.util.ReflectUtils; */ public class OnReaderFunction implements Function { + private static final Logger LOG = Log.getLogger(OnReaderFunction.class); private static final DynamicArgs.Builder ARGBUILDER; private static final Arg ARG_SESSION = new Arg(1, Session.class); - private static final Arg ARG_STREAM = new Arg(2, Reader.class); + private static final Arg ARG_STREAM = new Arg(2, Reader.class).required(); static { ARGBUILDER = new DynamicArgs.Builder(); - ARGBUILDER.addSignature(new ExactSignature(ARG_STREAM)); - ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_STREAM)); + ARGBUILDER.addSignature(ARG_STREAM, ARG_SESSION); } public static DynamicArgs.Builder getDynamicArgsBuilder() @@ -82,6 +84,11 @@ public class OnReaderFunction implements Function @Override public Void apply(Reader stream) { + if (LOG.isDebugEnabled()) + LOG.debug("apply({}, {}, {})", endpoint, session, stream); + + Objects.requireNonNull(stream, "Reader cannot be null"); + this.callable.invoke(endpoint, session, stream); return null; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnTextFunction.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnTextFunction.java index 3c15efbc1e7..4e9698ee248 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnTextFunction.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/OnTextFunction.java @@ -27,7 +27,6 @@ import org.eclipse.jetty.websocket.api.annotations.WebSocket; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.reflect.Arg; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs; -import org.eclipse.jetty.websocket.common.reflect.ExactSignature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; /** @@ -37,13 +36,12 @@ public class OnTextFunction implements Function { private static final DynamicArgs.Builder ARGBUILDER; private static final Arg ARG_SESSION = new Arg(1, Session.class); - private static final Arg ARG_TEXT = new Arg(2, String.class); + private static final Arg ARG_TEXT = new Arg(2, String.class).required(); static { ARGBUILDER = new DynamicArgs.Builder(); - ARGBUILDER.addSignature(new ExactSignature(ARG_TEXT)); - ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_TEXT)); + ARGBUILDER.addSignature(ARG_TEXT, ARG_SESSION); } public static DynamicArgs.Builder getDynamicArgsBuilder() diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ReaderMessageSink.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ReaderMessageSink.java index 512e538a725..d837f615f3b 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ReaderMessageSink.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/ReaderMessageSink.java @@ -23,8 +23,12 @@ import java.nio.ByteBuffer; import java.util.concurrent.Executor; import java.util.function.Function; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + public class ReaderMessageSink implements MessageSink { + private static final Logger LOG = Log.getLogger(ReaderMessageSink.class); private final Executor executor; private final Function onStreamFunction; private MessageReader stream; @@ -54,6 +58,8 @@ public class ReaderMessageSink implements MessageSink executor.execute(() -> { // processing of errors is the responsibility // of the stream function + if(LOG.isDebugEnabled()) + LOG.debug("onStreamFunction.apply({})", stream); onStreamFunction.apply(stream); }); } @@ -62,7 +68,11 @@ public class ReaderMessageSink implements MessageSink { if (fin) { + if(LOG.isDebugEnabled()) + LOG.debug("stream.awaitClose() - {}", stream); stream.awaitClose(); + if(LOG.isDebugEnabled()) + LOG.debug("stream recycled - {}", stream); stream = null; } } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/reflect/DynamicArgs.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/reflect/DynamicArgs.java index 403c6d5a55e..e5b9d5be6bd 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/reflect/DynamicArgs.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/reflect/DynamicArgs.java @@ -123,9 +123,9 @@ public class DynamicArgs return null; } - public Builder addSignature(Signature sig) + public Builder addSignature(Arg... args) { - signatures.add(sig); + signatures.add(new UnorderedSignature(args)); return this; } diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/reflect/ExactSignature.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/reflect/ExactSignature.java deleted file mode 100644 index b084b38915d..00000000000 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/reflect/ExactSignature.java +++ /dev/null @@ -1,173 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.common.reflect; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.function.BiFunction; -import java.util.function.Predicate; - -import org.eclipse.jetty.websocket.common.reflect.DynamicArgs.Signature; -import org.eclipse.jetty.websocket.common.util.ReflectUtils; - -public class ExactSignature implements Signature, Predicate -{ - private final Arg[] params; - - public ExactSignature() - { - this.params = new Arg[0]; - } - - public ExactSignature(Arg... params) - { - this.params = params; - } - - @Override - public Predicate getPredicate() - { - return this; - } - - @Override - public Arg[] getCallArgs() - { - return this.params; - } - - @Override - public boolean test(Method method) - { - Class[] types = method.getParameterTypes(); - if (types.length != params.length) - return false; - int len = params.length; - for (int i = 0; i < len; i++) - { - if (!params[i].getType().equals(types[i])) - return false; - } - return true; - } - - public void appendDescription(StringBuilder str) - { - str.append('('); - boolean delim = false; - for (Arg arg : params) - { - if (delim) - { - str.append(','); - } - str.append(' '); - str.append(arg.getName()); - if (arg.isArray()) - { - str.append("[]"); - } - delim = true; - } - str.append(')'); - } - - @Override - public BiFunction getInvoker(Method method, Arg... callArgs) - { - // Figure out mapping of calling args to method args - Class paramTypes[] = method.getParameterTypes(); - int paramTypesLength = paramTypes.length; - - // Method argument array pointing to index in calling array - int argMapping[] = new int[paramTypesLength]; - int callArgsLen = callArgs.length; - - for (int mi = 0; mi < paramTypesLength; mi++) - { - int ref = -1; - // Find reference to argument in callArgs - for (int ci = 0; ci < callArgsLen; ci++) - { - if (callArgs[ci].getIndex() == params[mi].getIndex()) - { - ref = ci; - } - } - if (ref < 0) - { - StringBuilder err = new StringBuilder(); - err.append("Unable to map type ["); - err.append(params[mi]); - err.append("] in method "); - ReflectUtils.append(err,method); - err.append(" to calling args: ("); - boolean delim = false; - for (Arg arg : callArgs) - { - if (delim) - err.append(", "); - err.append(arg); - delim = true; - } - err.append(")"); - - throw new DynamicArgsException(err.toString()); - } - argMapping[mi] = ref; - } - - // Return function capable of calling method - return (obj, potentialArgs) -> { - Object args[] = new Object[paramTypesLength]; - for (int i = 0; i < paramTypesLength; i++) - { - args[i] = potentialArgs[argMapping[i]]; - } - try - { - return method.invoke(obj,args); - } - catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) - { - StringBuilder err = new StringBuilder(); - err.append("Unable to call: "); - ReflectUtils.append(err,obj.getClass(),method); - err.append(" [with "); - boolean delim = false; - for (Object arg : args) - { - if (delim) - err.append(", "); - if (arg == null) - { - err.append(""); - } - else - { - err.append(arg.getClass().getSimpleName()); - } - delim = true; - } - err.append("]"); - throw new DynamicArgsException(err.toString(),e); - } - }; - } -} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/reflect/UnorderedSignature.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/reflect/UnorderedSignature.java index 18649f30a97..4eab7605658 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/reflect/UnorderedSignature.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/reflect/UnorderedSignature.java @@ -29,34 +29,34 @@ import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.common.reflect.DynamicArgs.Signature; import org.eclipse.jetty.websocket.common.util.ReflectUtils; -public class UnorderedSignature implements Signature, Predicate +class UnorderedSignature implements Signature, Predicate { private final static Logger LOG = Log.getLogger(UnorderedSignature.class); private final Arg[] params; - + public UnorderedSignature(Arg... args) { this.params = args; } - + @Override public Arg[] getCallArgs() { return this.params; } - + @Override public Predicate getPredicate() { return this; } - + @Override public boolean test(Method method) { return getArgMapping(method, false, params) != null; } - + public void appendDescription(StringBuilder str) { str.append('('); @@ -77,36 +77,52 @@ public class UnorderedSignature implements Signature, Predicate } str.append(')'); } - - private int[] getArgMapping(Method method, boolean throwOnFailure, Arg... callArgs) + + /** + * Identify mapping of argument indexes of the callArgs to method Args. + *

+ * The callArgs is what the websocket implementation code is + * using to call the method. + *

+ *

+ * The method Args are what the user endpoint method args + * are declared as. + *

+ * + * @param method the method that we want to eventually call + * @param throwOnFailure true to toss a {@link DynamicArgsException} if there is a problem + * attempting to identify the mapping. false to debug log the issue. + * @param callArgs the calling args for this signature + */ + public int[] getArgMapping(Method method, boolean throwOnFailure, Arg... callArgs) { int callArgsLen = callArgs.length; - + // Figure out mapping of calling args to method args Class paramTypes[] = method.getParameterTypes(); int paramTypesLength = paramTypes.length; - + // Method argument array pointing to index in calling array int argMapping[] = new int[paramTypesLength]; int argMappingLength = argMapping.length; - + // ServiceLoader for argument identification plugins List argIdentifiers = DynamicArgs.lookupArgIdentifiers(); Arg methodArgs[] = new Arg[paramTypesLength]; for (int pi = 0; pi < paramTypesLength; pi++) { methodArgs[pi] = new Arg(method, pi, paramTypes[pi]); - + // Supplement method argument identification from plugins for (ArgIdentifier argId : argIdentifiers) methodArgs[pi] = argId.apply(methodArgs[pi]); } - + // Iterate through mappings, looking for a callArg that fits it for (int ai = 0; ai < argMappingLength; ai++) { int ref = -1; - + // Find reference to argument in callArgs for (int ci = 0; ci < callArgsLen; ci++) { @@ -116,7 +132,7 @@ public class UnorderedSignature implements Signature, Predicate break; } } - + if (ref < 0) { StringBuilder err = new StringBuilder(); @@ -134,19 +150,24 @@ public class UnorderedSignature implements Signature, Predicate delim = true; } err.append(")"); - + if (throwOnFailure) + { throw new DynamicArgsException(err.toString()); + } else { - LOG.debug("{}", err.toString()); + if (LOG.isDebugEnabled()) + { + LOG.debug("{}", err.toString()); + } return null; } } - + argMapping[ai] = ref; } - + // Ensure that required arguments are present in the mapping for (int ci = 0; ci < callArgsLen; ci++) { @@ -168,7 +189,7 @@ public class UnorderedSignature implements Signature, Predicate err.append(callArgs[ci].getType()); err.append("] in method "); ReflectUtils.append(err, method); - + if (throwOnFailure) throw new DynamicArgsException(err.toString()); else @@ -179,33 +200,33 @@ public class UnorderedSignature implements Signature, Predicate } } } - + return argMapping; } - + @Override public BiFunction getInvoker(Method method, Arg... callArgs) { int argMapping[] = getArgMapping(method, true, callArgs); - + // Return function capable of calling method return new UnorderedParamsFunction(method, argMapping); } - + public static class UnorderedParamsFunction implements BiFunction { private final Method method; private final int paramTypesLength; private final int argMapping[]; - + public UnorderedParamsFunction(Method method, int argMapping[]) { this.method = method; this.paramTypesLength = method.getParameterTypes().length; this.argMapping = argMapping; } - + @Override public Object apply(Object obj, Object[] potentialArgs) { @@ -244,5 +265,5 @@ public class UnorderedSignature implements Signature, Predicate } } } - + } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctionsTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctionsTest.java index a3b62ff1ff5..eeb7b21d980 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctionsTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctionsTest.java @@ -32,6 +32,7 @@ import java.util.concurrent.TimeUnit; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.component.CloseableLifeCycle; import org.eclipse.jetty.websocket.api.Session; import org.eclipse.jetty.websocket.api.StatusCode; import org.eclipse.jetty.websocket.api.WebSocketConnectionListener; @@ -84,17 +85,21 @@ public class CommonEndpointFunctionsTest } @Test - public void testWebSocketConnectionListener_OpenTextClose() + public void testWebSocketConnectionListener_OpenTextClose() throws Exception { // Setup ConnectionOnly socket = new ConnectionOnly(); Session session = initSession(socket); - EndpointFunctions endpointFunctions = new CommonEndpointFunctions(socket, containerScope.getPolicy(), containerScope.getExecutor()); + try (CloseableLifeCycle lifecycle = new CloseableLifeCycle<>( + new CommonEndpointFunctions(socket, containerScope.getPolicy(), containerScope.getExecutor()))) + { + EndpointFunctions endpointFunctions = lifecycle.get(); - // Trigger Events - endpointFunctions.onOpen(session); - endpointFunctions.onText(BufferUtil.toBuffer("Hello World", UTF8), true); - endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); + // Trigger Events + endpointFunctions.onOpen(session); + endpointFunctions.onText(BufferUtil.toBuffer("Hello World", UTF8), true); + endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); + } // Validate Events socket.assertCaptured( @@ -118,17 +123,21 @@ public class CommonEndpointFunctionsTest } @Test - public void testWebSocketListener_OpenTextClose() + public void testWebSocketListener_OpenTextClose() throws Exception { // Setup DataConnection socket = new DataConnection(); Session session = initSession(socket); - EndpointFunctions endpointFunctions = new CommonEndpointFunctions(socket, containerScope.getPolicy(), containerScope.getExecutor()); + try (CloseableLifeCycle lifecycle = new CloseableLifeCycle<>( + new CommonEndpointFunctions(socket, containerScope.getPolicy(), containerScope.getExecutor()))) + { + EndpointFunctions endpointFunctions = lifecycle.get(); - // Trigger Events - endpointFunctions.onOpen(session); - endpointFunctions.onText(BufferUtil.toBuffer("Hello World", UTF8), true); - endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); + // Trigger Events + endpointFunctions.onOpen(session); + endpointFunctions.onText(BufferUtil.toBuffer("Hello World", UTF8), true); + endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); + } // Validate Events socket.assertCaptured( @@ -160,18 +169,22 @@ public class CommonEndpointFunctionsTest } } - @Test - public void testAnnotatedStreamedText_Single() throws InterruptedException + @Test(timeout = 1000) + public void testAnnotatedStreamedText_Single() throws Exception { // Setup StreamedText socket = new StreamedText(1); Session session = initSession(socket); - EndpointFunctions endpointFunctions = new CommonEndpointFunctions(socket, containerScope.getPolicy(), containerScope.getExecutor()); - // Trigger Events - endpointFunctions.onOpen(session); - endpointFunctions.onText(BufferUtil.toBuffer("Hello World", UTF8), true); - endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); + try (CloseableLifeCycle lifecycle = new CloseableLifeCycle<>( + new CommonEndpointFunctions(socket, containerScope.getPolicy(), containerScope.getExecutor()))) + { + EndpointFunctions endpointFunctions = lifecycle.get(); + // Trigger Events + endpointFunctions.onOpen(session); + endpointFunctions.onText(BufferUtil.toBuffer("Hello World", UTF8), true); + endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); + } // Await completion (of threads) socket.streamLatch.await(2, TimeUnit.SECONDS); @@ -180,21 +193,24 @@ public class CommonEndpointFunctionsTest socket.assertCaptured("onTextStream\\(Hello World\\)"); } - @Test - public void testAnnotatedStreamedText_MultipleParts() throws InterruptedException + @Test(timeout = 1000) + public void testAnnotatedStreamedText_MultipleParts() throws Exception { // Setup StreamedText socket = new StreamedText(1); Session session = initSession(socket); - EndpointFunctions endpointFunctions = new CommonEndpointFunctions(socket, containerScope.getPolicy(), containerScope.getExecutor()); - - // Trigger Events - endpointFunctions.onOpen(session); - endpointFunctions.onText(BufferUtil.toBuffer("Hel"), false); - endpointFunctions.onText(BufferUtil.toBuffer("lo "), false); - endpointFunctions.onText(BufferUtil.toBuffer("Wor"), false); - endpointFunctions.onText(BufferUtil.toBuffer("ld"), true); - endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); + try (CloseableLifeCycle lifecycle = new CloseableLifeCycle<>( + new CommonEndpointFunctions(socket, containerScope.getPolicy(), containerScope.getExecutor()))) + { + EndpointFunctions endpointFunctions = lifecycle.get(); + // Trigger Events + endpointFunctions.onOpen(session); + endpointFunctions.onText(BufferUtil.toBuffer("Hel"), false); + endpointFunctions.onText(BufferUtil.toBuffer("lo "), false); + endpointFunctions.onText(BufferUtil.toBuffer("Wor"), false); + endpointFunctions.onText(BufferUtil.toBuffer("ld"), true); + endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); + } // Await completion (of threads) socket.streamLatch.await(2, TimeUnit.SECONDS); @@ -219,20 +235,24 @@ public class CommonEndpointFunctionsTest } @Test - public void testWebSocketPartialListener() + public void testWebSocketPartialListener() throws Exception { // Setup PartialData socket = new PartialData(); Session session = initSession(socket); - EndpointFunctions endpointFunctions = new CommonEndpointFunctions(socket, containerScope.getPolicy(), containerScope.getExecutor()); + try (CloseableLifeCycle lifecycle = new CloseableLifeCycle<>( + new CommonEndpointFunctions(socket, containerScope.getPolicy(), containerScope.getExecutor()))) + { + EndpointFunctions endpointFunctions = lifecycle.get(); - // Trigger Events - endpointFunctions.onOpen(session); - endpointFunctions.onText(BufferUtil.toBuffer("Hel"), false); - endpointFunctions.onText(BufferUtil.toBuffer("lo "), false); - endpointFunctions.onText(BufferUtil.toBuffer("Wor"), false); - endpointFunctions.onText(BufferUtil.toBuffer("ld"), true); - endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); + // Trigger Events + endpointFunctions.onOpen(session); + endpointFunctions.onText(BufferUtil.toBuffer("Hel"), false); + endpointFunctions.onText(BufferUtil.toBuffer("lo "), false); + endpointFunctions.onText(BufferUtil.toBuffer("Wor"), false); + endpointFunctions.onText(BufferUtil.toBuffer("ld"), true); + endpointFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "Normal")); + } // Validate Events socket.assertCaptured( @@ -242,6 +262,6 @@ public class CommonEndpointFunctionsTest "onWebSocketPartialText\\(Wor, false\\)", "onWebSocketPartialText\\(ld, true\\)", "onWebSocketClose\\([^\\)]*\\)" - ); + ); } } diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/CloseableLocalWebSocketSession.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/CloseableLocalWebSocketSession.java index 9ff78cffaef..469c8cc4793 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/CloseableLocalWebSocketSession.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/CloseableLocalWebSocketSession.java @@ -18,15 +18,14 @@ package org.eclipse.jetty.websocket.common.io; -import org.eclipse.jetty.websocket.common.events.EventDriver; import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; import org.junit.rules.TestName; public class CloseableLocalWebSocketSession extends LocalWebSocketSession implements AutoCloseable { - public CloseableLocalWebSocketSession(WebSocketContainerScope containerScope, TestName testname, EventDriver driver) + public CloseableLocalWebSocketSession(WebSocketContainerScope containerScope, TestName testname, Object websocket) { - super(containerScope, testname, driver); + super(containerScope, testname, websocket); // LifeCycle start try { diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java index 6f07b78e433..440d7f8e008 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageOutputStreamTest.java @@ -18,7 +18,10 @@ package org.eclipse.jetty.websocket.common.message; -import java.net.URISyntaxException; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; + import java.util.Arrays; import org.eclipse.jetty.toolchain.test.TestTracker; @@ -39,10 +42,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; - public class MessageOutputStreamTest { private static final Logger LOG = Log.getLogger(MessageOutputStreamTest.class); @@ -59,16 +58,19 @@ public class MessageOutputStreamTest private WebSocketPolicy policy; private TrackingSocket remoteSocket; private LocalWebSocketSession session; - + private WebSocketSession remoteSession; + @After public void closeSession() throws Exception { session.close(); session.stop(); + remoteSession.close(); + remoteSession.stop(); } @Before - public void setupSession() throws URISyntaxException + public void setupSession() throws Exception { policy = WebSocketPolicy.newServerPolicy(); policy.setInputBufferSize(1024); @@ -79,8 +81,9 @@ public class MessageOutputStreamTest // remote socket remoteSocket = new TrackingSocket("remote"); - WebSocketSession remoteSession = new LocalWebSocketSession(containerScope,testname,remoteSocket); + remoteSession = new LocalWebSocketSession(containerScope,testname,remoteSocket); OutgoingFrames socketPipe = FramePipes.to(remoteSession); + remoteSession.start(); remoteSession.open(); // Local Session diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java index 30865b67565..3c8a719e83a 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java @@ -21,7 +21,6 @@ package org.eclipse.jetty.websocket.common.message; import static org.hamcrest.Matchers.is; import java.net.URI; -import java.net.URISyntaxException; import java.util.Arrays; import org.eclipse.jetty.toolchain.test.TestTracker; @@ -65,10 +64,11 @@ public class MessageWriterTest { session.close(); remoteSession.close(); + remoteSession.stop(); } @Before - public void setupSession() throws URISyntaxException + public void setupSession() throws Exception { policy = WebSocketPolicy.newServerPolicy(); policy.setInputBufferSize(1024); @@ -83,6 +83,7 @@ public class MessageWriterTest LocalWebSocketConnection remoteConnection = new LocalWebSocketConnection(bufferPool); remoteSession = new WebSocketSession(containerScope,remoteURI,remoteSocket,remoteConnection); OutgoingFrames socketPipe = FramePipes.to(remoteSession); + remoteSession.start(); remoteSession.open(); // Local Session diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/reflect/DynamicArgsTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/reflect/DynamicArgsTest.java new file mode 100644 index 00000000000..af32e0cf28d --- /dev/null +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/reflect/DynamicArgsTest.java @@ -0,0 +1,187 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.websocket.common.reflect; + +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertThat; + +import java.io.File; +import java.lang.reflect.Method; + +import org.eclipse.jetty.util.annotation.Name; +import org.junit.Test; + +public class DynamicArgsTest +{ + @SuppressWarnings("unused") + public static class SampleSignatures + { + public String sigEmpty() + { + return "sigEmpty<>"; + } + + public String sigStr(String str) + { + return String.format("sigStr<%s>", str); + } + + public String sigStrFile(String str, File foo) + { + return String.format("sigStrFile<%s,%s>", str, foo); + } + + public String sigFileStr(File foo, String str) + { + return String.format("sigFileStr<%s,%s>", foo, str); + } + + public String sigFileStrFin(File foo, String str, @Name("fin") boolean fin) + { + return String.format("sigFileStrFin<%s,%s,%b>", foo, str, fin); + } + + public String sigByteArray(byte[] buf, @Name("offset") int offset, @Name("length") int len) + { + return String.format("sigByteArray<%s,%d,%d>", buf == null ? "" : ("[" + buf.length + "]"), offset, len); + } + } + + public static Method findMethodByName(Object obj, String name) + { + for (Method method : obj.getClass().getMethods()) + { + if (method.getName().equals(name)) + { + return method; + } + } + throw new AssertionError("Unable to find method: " + name); + } + + /** + * Test with method that has empty signature, + * and desired callable that also has an empty signature + * + * @throws Exception on error + */ + @Test + public void testEmptySignature() throws Exception + { + DynamicArgs.Builder dab = new DynamicArgs.Builder(); + dab.addSignature(); // intentionally empty + + SampleSignatures samples = new SampleSignatures(); + Method m = findMethodByName(samples, "sigEmpty"); + DynamicArgs dynamicArgs = dab.build(m); + assertThat("DynamicArgs", dynamicArgs, notNullValue()); + + // Test with empty potential args + String result = (String) dynamicArgs.invoke(samples); + assertThat("result", result, is("sigEmpty<>")); + } + + /** + * Test with method that has empty signature, + * and desired callable that has a String (optional) signature + * + * @throws Exception on error + */ + @Test + public void testEmptySignature_StringCallable() throws Exception + { + final Arg ARG_STR = new Arg(String.class); + + DynamicArgs.Builder dab = new DynamicArgs.Builder(); + dab.addSignature(ARG_STR); + + SampleSignatures samples = new SampleSignatures(); + Method m = findMethodByName(samples, "sigEmpty"); + DynamicArgs dynamicArgs = dab.build(m); + assertThat("DynamicArgs", dynamicArgs, notNullValue()); + + // Test with empty potential args + String result = (String) dynamicArgs.invoke(samples, "Hello"); + assertThat("result", result, is("sigEmpty<>")); + } + + /** + * Test with method that has String signature, and + * a desired callable that also has String signature. + * + * @throws Exception on error + */ + @Test + public void testStringSignature() throws Exception + { + final Arg ARG_STR = new Arg(String.class); + + DynamicArgs.Builder dab = new DynamicArgs.Builder(); + dab.addSignature(ARG_STR); + + final Arg CALL_STR = new Arg(String.class); + + SampleSignatures samples = new SampleSignatures(); + Method m = findMethodByName(samples, "sigStr"); + DynamicArgs dynamicArgs = dab.build(m, CALL_STR); + assertThat("DynamicArgs", dynamicArgs, notNullValue()); + + // Test with potential args + String result = (String) dynamicArgs.invoke(samples, "Hello"); + assertThat("result", result, is("sigStr")); + } + + /** + * Test of finding a match on a method that is tagged + * via the ArgIdentifier concepts. + * + * @throws Exception on error + */ + @Test + public void testByteArraySignature() throws Exception + { + final Arg ARG_BYTEARRAY = new Arg(byte[].class); + final Arg ARG_OFFSET = new Arg(int.class).setTag("offset"); + final Arg ARG_LENGTH = new Arg(int.class).setTag("length"); + + DynamicArgs.Builder dab = new DynamicArgs.Builder(); + dab.addSignature(ARG_BYTEARRAY, ARG_OFFSET, ARG_LENGTH); + + final Arg CALL_BYTEARRAY = new Arg(byte[].class); + final Arg CALL_OFFSET = new Arg(int.class).setTag("offset"); + final Arg CALL_LENGTH = new Arg(int.class).setTag("length"); + + SampleSignatures ssigs = new SampleSignatures(); + Method m = findMethodByName(ssigs, "sigByteArray"); + DynamicArgs dynamicArgs = dab.build(m, CALL_BYTEARRAY, CALL_OFFSET, CALL_LENGTH); + assertThat("DynamicArgs", dynamicArgs, notNullValue()); + + // Test with potential args + byte buf[] = new byte[222]; + int offset = 3; + int len = 44; + String result = (String) dynamicArgs.invoke(ssigs, buf, offset, len); + assertThat("result", result, is("sigByteArray<[222],3,44>")); + + // Test with empty potential args + result = (String) dynamicArgs.invoke(ssigs, null, 123, 456); + assertThat("result", result, is("sigByteArray<,123,456>")); + } +} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/reflect/ExactSignatureTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/reflect/ExactSignatureTest.java deleted file mode 100644 index f1530aa1abc..00000000000 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/reflect/ExactSignatureTest.java +++ /dev/null @@ -1,123 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.common.reflect; - -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.Assert.assertThat; - -import java.io.File; -import java.lang.reflect.Method; - -import org.junit.Test; - -public class ExactSignatureTest -{ - public static class SampleSignatures - { - public String sigEmpty() - { - return "sigEmpty<>"; - } - - public String sigStr(String str) - { - return String.format("sigStr<%s>", str); - } - - public String sigByteArray(byte[] buf, int offset, int len) - { - return String.format("sigByteArray<%s,%d,%d>", buf == null ? "" : ("[" + buf.length + "]"), offset, len); - } - } - - public static Method findMethodByName(Object obj, String name) - { - for (Method method : obj.getClass().getMethods()) - { - if (method.getName().equals(name)) - { - return method; - } - } - throw new AssertionError("Unable to find method: " + name); - } - - private static final Arg ARG_STR = new Arg(1, String.class); - private static final Arg ARG_BOOL = new Arg(2, Boolean.class); - private static final Arg ARG_FILE = new Arg(3, File.class); - private static final Arg ARG_BYTEARRAY = new Arg(4, byte[].class); - private static final Arg ARG_OFFSET = new Arg(5, int.class); - private static final Arg ARG_LEN = new Arg(6, int.class); - - @Test - public void testEmptySignature() throws Exception - { - DynamicArgs.Builder dab = new DynamicArgs.Builder(); - dab.addSignature(new ExactSignature()); - - SampleSignatures ssigs = new SampleSignatures(); - Method m = findMethodByName(ssigs, "sigEmpty"); - DynamicArgs dargs = dab.build(m, ARG_STR, ARG_BOOL, ARG_FILE); - assertThat("DynamicArgs", dargs, notNullValue()); - - // Test with potential args - String result = (String) dargs.invoke(ssigs, "Hello", Boolean.TRUE, new File("bar")); - assertThat("result", result, is("sigEmpty<>")); - } - - @Test - public void testStringSignature() throws Exception - { - DynamicArgs.Builder dab = new DynamicArgs.Builder(); - dab.addSignature(new ExactSignature(ARG_STR)); - - SampleSignatures ssigs = new SampleSignatures(); - Method m = findMethodByName(ssigs, "sigStr"); - DynamicArgs dargs = dab.build(m, ARG_STR, ARG_BOOL, ARG_FILE); - assertThat("DynamicArgs", dargs, notNullValue()); - - // Test with potential args - String result = (String) dargs.invoke(ssigs, "Hello", Boolean.TRUE, new File("bar")); - assertThat("result", result, is("sigStr")); - } - - @Test - public void testByteArraySignature() throws Exception - { - DynamicArgs.Builder dab = new DynamicArgs.Builder(); - dab.addSignature(new ExactSignature(ARG_BYTEARRAY, ARG_OFFSET, ARG_LEN)); - - SampleSignatures ssigs = new SampleSignatures(); - Method m = findMethodByName(ssigs, "sigByteArray"); - DynamicArgs dargs = dab.build(m, ARG_BYTEARRAY, ARG_OFFSET, ARG_LEN); - assertThat("DynamicArgs", dargs, notNullValue()); - - // Test with potential args - byte buf[] = new byte[222]; - int offset = 3; - int len = 44; - String result = (String) dargs.invoke(ssigs, buf, offset, len); - assertThat("result", result, is("sigByteArray<[222],3,44>")); - - // Test with empty potential args - result = (String) dargs.invoke(ssigs, null, 123, 456); - assertThat("result", result, is("sigByteArray<,123,456>")); - } -} diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/reflect/UnorderedSignatureTest.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/reflect/UnorderedSignatureTest.java index eb4e30fb3d3..a929bdf0fca 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/reflect/UnorderedSignatureTest.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/reflect/UnorderedSignatureTest.java @@ -26,44 +26,52 @@ import java.io.File; import java.lang.reflect.Method; import org.eclipse.jetty.util.annotation.Name; +import org.eclipse.jetty.websocket.api.Session; import org.junit.Test; public class UnorderedSignatureTest { - @SuppressWarnings("unused") public static class SampleSignatures { public String sigEmpty() { return "sigEmpty<>"; } - + public String sigStr(String str) { - return String.format("sigStr<%s>",str); + return String.format("sigStr<%s>", str); } - + public String sigStrFile(String str, File foo) { - return String.format("sigStrFile<%s,%s>",str,foo); + return String.format("sigStrFile<%s,%s>", str, q(foo)); } - + public String sigFileStr(File foo, String str) { - return String.format("sigFileStr<%s,%s>",foo,str); + return String.format("sigFileStr<%s,%s>", q(foo), str); } - + public String sigFileStrFin(File foo, String str, @Name("fin") boolean fin) { - return String.format("sigFileStrFin<%s,%s,%b>",foo,str,fin); + return String.format("sigFileStrFin<%s,%s,%b>", q(foo), q(str), fin); } - - public String sigByteArray(byte[] buf, @Name("offset")int offset, @Name("length")int len) + + public String sigByteArray(byte[] buf, @Name("offset") int offset, @Name("length") int len) { - return String.format("sigByteArray<%s,%d,%d>",buf == null ? "" : ("[" + buf.length + "]"),offset,len); + return String.format("sigByteArray<%s,%d,%d>", buf == null ? "" : ("[" + buf.length + "]"), offset, len); + } + + private String q(Object obj) + { + if (obj == null) + return ""; + else + return obj.toString(); } } - + public static Method findMethodByName(Object obj, String name) { for (Method method : obj.getClass().getMethods()) @@ -75,110 +83,156 @@ public class UnorderedSignatureTest } throw new AssertionError("Unable to find method: " + name); } - - private static final Arg ARG_STR = new Arg(String.class); - private static final Arg ARG_BOOL = new Arg(Boolean.class); - private static final Arg ARG_FILE = new Arg(File.class); - private static final Arg ARG_BYTEARRAY = new Arg(byte[].class); - private static final Arg ARG_OFFSET = new Arg(int.class).setTag("offset"); - private static final Arg ARG_LENGTH = new Arg(int.class).setTag("length"); - private static final Arg ARG_FIN = new Arg(Boolean.class).setTag("fin"); - - /** - * Test with method that has empty signature, - * and desired callable that also has an empty signature - * @throws Exception on error - */ - @Test - public void testEmptySignature() throws Exception + + private void assertMappings(int actualMapping[], int... expectedMapping) { - DynamicArgs.Builder dab = new DynamicArgs.Builder(); - dab.addSignature(new UnorderedSignature()); - - SampleSignatures samples = new SampleSignatures(); - Method m = findMethodByName(samples, "sigEmpty"); - DynamicArgs dynamicArgs = dab.build(m); - assertThat("DynamicArgs", dynamicArgs, notNullValue()); - - // Test with empty potential args - String result = (String) dynamicArgs.invoke(samples); - assertThat("result", result, is("sigEmpty<>")); + assertThat("mapping", actualMapping, notNullValue()); + assertThat("mapping.length", actualMapping.length, is(expectedMapping.length)); + if (expectedMapping.length > 0) + { + for (int i = 0; i < expectedMapping.length; i++) + { + assertThat("mapping[" + i + "]", actualMapping[i], is(expectedMapping[i])); + } + } } - - /** - * Test with method that has empty signature, - * and desired callable that has a String (optional) signature - * @throws Exception on error - */ + @Test - public void testEmptySignature_StringCallable - () throws Exception + public void testEmpty_Call_Session() { - DynamicArgs.Builder dab = new DynamicArgs.Builder(); - dab.addSignature(new UnorderedSignature(ARG_STR)); - + UnorderedSignature sig = new UnorderedSignature(new Arg(Session.class)); SampleSignatures samples = new SampleSignatures(); - Method m = findMethodByName(samples, "sigEmpty"); - DynamicArgs dynamicArgs = dab.build(m); - assertThat("DynamicArgs", dynamicArgs, notNullValue()); - - // Test with empty potential args - String result = (String) dynamicArgs.invoke(samples, "Hello"); - assertThat("result", result, is("sigEmpty<>")); + Method method = findMethodByName(samples, "sigEmpty"); + + int mapping[] = sig.getArgMapping(method, false, new Arg(Session.class)); + assertMappings(mapping); } - - /** - * Test with method that has String signature, and - * a desired callable that also has String signature. - * @throws Exception on error - */ + @Test - public void testStringSignature() throws Exception + public void testEmpty_Call_None() { - DynamicArgs.Builder dab = new DynamicArgs.Builder(); - dab.addSignature(new UnorderedSignature(ARG_STR)); - - final Arg CALL_STR = new Arg(String.class); - + UnorderedSignature sig = new UnorderedSignature(); SampleSignatures samples = new SampleSignatures(); - Method m = findMethodByName(samples, "sigStr"); - DynamicArgs dynamicArgs = dab.build(m, CALL_STR); - assertThat("DynamicArgs", dynamicArgs, notNullValue()); - - // Test with potential args - String result = (String) dynamicArgs.invoke(samples, "Hello"); - assertThat("result", result, is("sigStr")); + Method method = findMethodByName(samples, "sigEmpty"); + + int mapping[] = sig.getArgMapping(method, false); + assertMappings(mapping); } - - /** - * Test of finding a match on a method that is tagged - * via a the ArgIdentifier concepts. - * @throws Exception on error - */ + @Test - public void testByteArraySignature() throws Exception + public void testString_Call_String() { - DynamicArgs.Builder dab = new DynamicArgs.Builder(); - dab.addSignature(new UnorderedSignature(ARG_BYTEARRAY, ARG_OFFSET, ARG_LENGTH)); - - final Arg CALL_BYTEARRAY = new Arg(byte[].class); - final Arg CALL_OFFSET = new Arg(int.class).setTag("offset"); - final Arg CALL_LENGTH = new Arg(int.class).setTag("length"); - - SampleSignatures ssigs = new SampleSignatures(); - Method m = findMethodByName(ssigs, "sigByteArray"); - DynamicArgs dynamicArgs = dab.build(m,CALL_BYTEARRAY, CALL_OFFSET, CALL_LENGTH); - assertThat("DynamicArgs", dynamicArgs, notNullValue()); - - // Test with potential args - byte buf[] = new byte[222]; - int offset = 3; - int len = 44; - String result = (String)dynamicArgs.invoke(ssigs,buf,offset,len); - assertThat("result", result, is("sigByteArray<[222],3,44>")); - - // Test with empty potential args - result = (String)dynamicArgs.invoke(ssigs,null,123,456); - assertThat("result", result, is("sigByteArray<,123,456>")); + UnorderedSignature sig = new UnorderedSignature(); + SampleSignatures samples = new SampleSignatures(); + Method method = findMethodByName(samples, "sigStr"); + + int mapping[] = sig.getArgMapping(method, false, new Arg(String.class)); + assertMappings(mapping, 0); + } + + @Test + public void testString_Call_Session_String() + { + UnorderedSignature sig = new UnorderedSignature(); + SampleSignatures samples = new SampleSignatures(); + Method method = findMethodByName(samples, "sigStr"); + + int mapping[] = sig.getArgMapping(method, false, new Arg(Session.class), new Arg(String.class)); + assertMappings(mapping, 1); + } + + @Test + public void testStringFile_Call_String_File() + { + UnorderedSignature sig = new UnorderedSignature(); + SampleSignatures samples = new SampleSignatures(); + Method method = findMethodByName(samples, "sigStrFile"); + + int mapping[] = sig.getArgMapping(method, false, new Arg(String.class), new Arg(File.class)); + assertMappings(mapping, 0, 1); + } + + @Test + public void testStringFile_Call_File_String() + { + UnorderedSignature sig = new UnorderedSignature(); + SampleSignatures samples = new SampleSignatures(); + Method method = findMethodByName(samples, "sigStrFile"); + + int mapping[] = sig.getArgMapping(method, false, new Arg(File.class), new Arg(String.class)); + assertMappings(mapping, 1, 0); + } + + @Test + public void testFileString_Call_String_File() + { + UnorderedSignature sig = new UnorderedSignature(); + SampleSignatures samples = new SampleSignatures(); + Method method = findMethodByName(samples, "sigFileStr"); + + int mapping[] = sig.getArgMapping(method, false, new Arg(String.class), new Arg(File.class)); + assertMappings(mapping, 1, 0); + } + + @Test + public void testFileString_Call_File_String() + { + UnorderedSignature sig = new UnorderedSignature(); + SampleSignatures samples = new SampleSignatures(); + Method method = findMethodByName(samples, "sigFileStr"); + + int mapping[] = sig.getArgMapping(method, false, new Arg(File.class), new Arg(String.class)); + assertMappings(mapping, 0, 1); + } + + @Test + public void testFileStringFin_Call_File_String_BoolTag() + { + UnorderedSignature sig = new UnorderedSignature(); + SampleSignatures samples = new SampleSignatures(); + Method method = findMethodByName(samples, "sigFileStrFin"); + + Arg callArgs[] = {new Arg(File.class), new Arg(String.class), new Arg(boolean.class).setTag("fin")}; + + int mapping[] = sig.getArgMapping(method, false, callArgs); + assertMappings(mapping, 0, 1, 2); + + Object params[] = {new File("foo"), "bar", true}; + String resp = (String) sig.getInvoker(method, callArgs).apply(samples, params); + assertThat("Invoked response", resp, is("sigFileStrFin")); + } + + @Test + public void testFileStringFin_Call_BoolTag_File_String() + { + UnorderedSignature sig = new UnorderedSignature(); + SampleSignatures samples = new SampleSignatures(); + Method method = findMethodByName(samples, "sigFileStrFin"); + + Arg callArgs[] = {new Arg(boolean.class).setTag("fin"), new Arg(File.class), new Arg(String.class)}; + + int mapping[] = sig.getArgMapping(method, false, callArgs); + assertMappings(mapping, 1, 2, 0); + + Object params[] = {true, new File("foo"), "bar"}; + String resp = (String) sig.getInvoker(method, callArgs).apply(samples, params); + assertThat("Invoked response", resp, is("sigFileStrFin")); + } + + @Test + public void testFileStringFin_Call_BoolTag_Null_String() + { + UnorderedSignature sig = new UnorderedSignature(); + SampleSignatures samples = new SampleSignatures(); + Method method = findMethodByName(samples, "sigFileStrFin"); + + Arg callArgs[] = {new Arg(boolean.class).setTag("fin"), new Arg(File.class), new Arg(String.class)}; + + int mapping[] = sig.getArgMapping(method, false, callArgs); + assertMappings(mapping, 1, 2, 0); + + Object params[] = {true, null, "bar"}; + String resp = (String) sig.getInvoker(method, callArgs).apply(samples, params); + assertThat("Invoked response", resp, is("sigFileStrFin<,bar,true>")); } } diff --git a/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties b/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties index f7c293f88f5..0fee6997169 100644 --- a/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties +++ b/jetty-websocket/websocket-common/src/test/resources/jetty-logging.properties @@ -1,8 +1,9 @@ org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog org.eclipse.jetty.LEVEL=WARN -# org.eclipse.jetty.websocket.LEVEL=DEBUG +org.eclipse.jetty.websocket.LEVEL=DEBUG # org.eclipse.jetty.websocket.protocol.Parser.LEVEL=DEBUG # org.eclipse.jetty.websocket.protocol.LEVEL=DEBUG # org.eclipse.jetty.websocket.io.payload.LEVEL=DEBUG # org.eclipse.jetty.websocket.common.extensions.LEVEL=DEBUG # org.eclipse.jetty.websocket.common.message.LEVEL=DEBUG +org.eclipse.jetty.websocket.common.function.LEVEL=DEBUG