diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/AbstractMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/AbstractMessageSink.java
index fa6349e1f11..979098405bd 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/AbstractMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/AbstractMessageSink.java
@@ -13,10 +13,10 @@
package org.eclipse.jetty.websocket.core.messages;
-import java.lang.invoke.MethodHandle;
import java.util.Objects;
import org.eclipse.jetty.websocket.core.CoreSession;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
/**
*
Abstract implementation of {@link MessageSink}.
@@ -42,21 +42,21 @@ import org.eclipse.jetty.websocket.core.CoreSession;
public abstract class AbstractMessageSink implements MessageSink
{
private final CoreSession session;
- private final MethodHandle methodHandle;
+ private final MethodHolder methodHandle;
private final boolean autoDemand;
/**
* Creates a new {@link MessageSink}.
*
* @param session the WebSocket session
- * @param methodHandle the application function to invoke
+ * @param methodHolder the application function to invoke
* @param autoDemand whether this {@link MessageSink} manages demand automatically
* as explained in {@link AbstractMessageSink}
*/
- public AbstractMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public AbstractMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
this.session = Objects.requireNonNull(session, "CoreSession");
- this.methodHandle = Objects.requireNonNull(methodHandle, "MethodHandle");
+ this.methodHandle = Objects.requireNonNull(methodHolder, "MethodHolder");
this.autoDemand = autoDemand;
}
@@ -73,7 +73,7 @@ public abstract class AbstractMessageSink implements MessageSink
* Get the application function.
* @return the application function
*/
- public MethodHandle getMethodHandle()
+ public MethodHolder getMethodHolder()
{
return methodHandle;
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ByteArrayMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ByteArrayMessageSink.java
index 2ee097d032a..ee77a8dba81 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ByteArrayMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ByteArrayMessageSink.java
@@ -13,8 +13,6 @@
package org.eclipse.jetty.websocket.core.messages;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;
import org.eclipse.jetty.io.RetainableByteBuffer;
@@ -22,8 +20,8 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
-import org.eclipse.jetty.websocket.core.exception.InvalidSignatureException;
import org.eclipse.jetty.websocket.core.exception.MessageTooLargeException;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
/**
* A {@link MessageSink} implementation that accumulates BINARY frames
@@ -38,17 +36,12 @@ public class ByteArrayMessageSink extends AbstractMessageSink
* Creates a new {@link ByteArrayMessageSink}.
*
* @param session the WebSocket session
- * @param methodHandle the application function to invoke when a new message has been assembled
+ * @param methodHolder the application function to invoke when a new message has been assembled
* @param autoDemand whether this {@link MessageSink} manages demand automatically
*/
- public ByteArrayMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public ByteArrayMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
- super(session, methodHandle, autoDemand);
- // This uses the offset length byte array signature not supported by jakarta websocket.
- // The jakarta layer instead uses decoders for whole byte array messages instead of this message sink.
- MethodType onMessageType = MethodType.methodType(Void.TYPE, byte[].class, int.class, int.class);
- if (methodHandle.type().changeReturnType(void.class) != onMessageType.changeReturnType(void.class))
- throw InvalidSignatureException.build(onMessageType, methodHandle.type());
+ super(session, methodHolder, autoDemand);
}
@Override
@@ -70,7 +63,7 @@ public class ByteArrayMessageSink extends AbstractMessageSink
if (frame.isFin() && (accumulator == null || accumulator.isEmpty()))
{
byte[] buf = BufferUtil.toArray(payload);
- getMethodHandle().invoke(buf, 0, buf.length);
+ getMethodHolder().invoke(buf, 0, buf.length);
callback.succeeded();
autoDemand();
return;
@@ -93,7 +86,7 @@ public class ByteArrayMessageSink extends AbstractMessageSink
callback = Callback.NOOP;
int length = accumulator.remaining();
byte[] buf = accumulator.takeByteArray();
- getMethodHandle().invoke(buf, 0, length);
+ getMethodHolder().invoke(buf, 0, length);
autoDemand();
}
else
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ByteBufferMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ByteBufferMessageSink.java
index 2783387b338..41d1df5210f 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ByteBufferMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ByteBufferMessageSink.java
@@ -13,8 +13,6 @@
package org.eclipse.jetty.websocket.core.messages;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;
import org.eclipse.jetty.io.ByteBufferCallbackAccumulator;
@@ -23,8 +21,8 @@ import org.eclipse.jetty.io.RetainableByteBuffer;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
-import org.eclipse.jetty.websocket.core.exception.InvalidSignatureException;
import org.eclipse.jetty.websocket.core.exception.MessageTooLargeException;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
/**
*
A {@link MessageSink} implementation that accumulates BINARY frames
@@ -39,24 +37,12 @@ public class ByteBufferMessageSink extends AbstractMessageSink
* Creates a new {@link ByteBufferMessageSink}.
*
* @param session the WebSocket session
- * @param methodHandle the application function to invoke when a new message has been assembled
+ * @param methodHolder the application function to invoke when a new message has been assembled
* @param autoDemand whether this {@link MessageSink} manages demand automatically
*/
- public ByteBufferMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public ByteBufferMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
- this(session, methodHandle, autoDemand, true);
- }
-
- protected ByteBufferMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand, boolean validateSignature)
- {
- super(session, methodHandle, autoDemand);
-
- if (validateSignature)
- {
- MethodType onMessageType = MethodType.methodType(Void.TYPE, ByteBuffer.class);
- if (methodHandle.type() != onMessageType)
- throw InvalidSignatureException.build(onMessageType, methodHandle.type());
- }
+ super(session, methodHolder, autoDemand);
}
@Override
@@ -76,7 +62,7 @@ public class ByteBufferMessageSink extends AbstractMessageSink
// created or used, then we don't need to aggregate.
if (frame.isFin() && (accumulator == null || accumulator.getLength() == 0))
{
- invoke(getMethodHandle(), frame.getPayload(), callback);
+ invoke(getMethodHolder(), frame.getPayload(), callback);
autoDemand();
return;
}
@@ -99,7 +85,7 @@ public class ByteBufferMessageSink extends AbstractMessageSink
ByteBuffer byteBuffer = buffer.getByteBuffer();
accumulator.writeTo(byteBuffer);
callback = Callback.from(buffer::release);
- invoke(getMethodHandle(), byteBuffer, callback);
+ invoke(getMethodHolder(), byteBuffer, callback);
autoDemand();
}
else
@@ -122,9 +108,9 @@ public class ByteBufferMessageSink extends AbstractMessageSink
accumulator.fail(failure);
}
- protected void invoke(MethodHandle methodHandle, ByteBuffer byteBuffer, Callback callback) throws Throwable
+ protected void invoke(MethodHolder methodHolder, ByteBuffer byteBuffer, Callback callback) throws Throwable
{
- methodHandle.invoke(byteBuffer);
+ methodHolder.invoke(byteBuffer);
callback.succeeded();
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/DispatchedMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/DispatchedMessageSink.java
index 7deb4ed60d8..44ea17285b2 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/DispatchedMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/DispatchedMessageSink.java
@@ -16,7 +16,6 @@ package org.eclipse.jetty.websocket.core.messages;
import java.io.Closeable;
import java.io.InputStream;
import java.io.Reader;
-import java.lang.invoke.MethodHandle;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.Executor;
@@ -26,6 +25,7 @@ import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.websocket.core.CloseStatus;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
/**
*
A partial implementation of {@link MessageSink} for methods that consume WebSocket
@@ -51,9 +51,9 @@ public abstract class DispatchedMessageSink extends AbstractMessageSink
private volatile CompletableFuture dispatchComplete;
private MessageSink typeSink;
- public DispatchedMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public DispatchedMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
- super(session, methodHandle, autoDemand);
+ super(session, methodHolder, autoDemand);
if (!autoDemand)
throw new IllegalArgumentException("%s must be auto-demanding".formatted(getClass().getSimpleName()));
executor = session.getWebSocketComponents().getExecutor();
@@ -74,7 +74,7 @@ public abstract class DispatchedMessageSink extends AbstractMessageSink
{
try
{
- getMethodHandle().invoke(typeSink);
+ getMethodHolder().invoke(typeSink);
if (typeSink instanceof Closeable closeable)
IO.close(closeable);
dispatchComplete.complete(null);
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/InputStreamMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/InputStreamMessageSink.java
index 72c65802387..bbf826747cb 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/InputStreamMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/InputStreamMessageSink.java
@@ -13,15 +13,14 @@
package org.eclipse.jetty.websocket.core.messages;
-import java.lang.invoke.MethodHandle;
-
import org.eclipse.jetty.websocket.core.CoreSession;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class InputStreamMessageSink extends DispatchedMessageSink
{
- public InputStreamMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public InputStreamMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
- super(session, methodHandle, autoDemand);
+ super(session, methodHolder, autoDemand);
}
@Override
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialByteArrayMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialByteArrayMessageSink.java
index c07b35484bc..37da9c08c2c 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialByteArrayMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialByteArrayMessageSink.java
@@ -13,12 +13,11 @@
package org.eclipse.jetty.websocket.core.messages;
-import java.lang.invoke.MethodHandle;
-
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
/**
* A {@link MessageSink} implementation that delivers BINARY frames
@@ -31,12 +30,12 @@ public class PartialByteArrayMessageSink extends AbstractMessageSink
* Creates a new {@link PartialByteArrayMessageSink}.
*
* @param session the WebSocket session
- * @param methodHandle the application function to invoke when a new frame has arrived
+ * @param methodHolder the application function to invoke when a new frame has arrived
* @param autoDemand whether this {@link MessageSink} manages demand automatically
*/
- public PartialByteArrayMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public PartialByteArrayMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
- super(session, methodHandle, autoDemand);
+ super(session, methodHolder, autoDemand);
}
@Override
@@ -47,7 +46,7 @@ public class PartialByteArrayMessageSink extends AbstractMessageSink
if (frame.hasPayload() || frame.isFin())
{
byte[] buffer = BufferUtil.toArray(frame.getPayload());
- getMethodHandle().invoke(buffer, frame.isFin());
+ getMethodHolder().invoke(buffer, frame.isFin());
callback.succeeded();
autoDemand();
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialByteBufferMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialByteBufferMessageSink.java
index 5cdf0ebba02..9fd7bf57beb 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialByteBufferMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialByteBufferMessageSink.java
@@ -13,12 +13,12 @@
package org.eclipse.jetty.websocket.core.messages;
-import java.lang.invoke.MethodHandle;
import java.nio.ByteBuffer;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
/**
*
A {@link MessageSink} implementation that delivers BINARY frames
@@ -31,12 +31,12 @@ public class PartialByteBufferMessageSink extends AbstractMessageSink
* Creates a new {@link PartialByteBufferMessageSink}.
*
* @param session the WebSocket session
- * @param methodHandle the application function to invoke when a new frame has arrived
+ * @param methodHolder the application function to invoke when a new frame has arrived
* @param autoDemand whether this {@link MessageSink} manages demand automatically
*/
- public PartialByteBufferMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public PartialByteBufferMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
- super(session, methodHandle, autoDemand);
+ super(session, methodHolder, autoDemand);
}
@Override
@@ -46,7 +46,7 @@ public class PartialByteBufferMessageSink extends AbstractMessageSink
{
if (frame.hasPayload() || frame.isFin())
{
- invoke(getMethodHandle(), frame.getPayload(), frame.isFin(), callback);
+ invoke(getMethodHolder(), frame.getPayload(), frame.isFin(), callback);
autoDemand();
}
else
@@ -61,9 +61,9 @@ public class PartialByteBufferMessageSink extends AbstractMessageSink
}
}
- protected void invoke(MethodHandle methodHandle, ByteBuffer byteBuffer, boolean fin, Callback callback) throws Throwable
+ protected void invoke(MethodHolder methodHolder, ByteBuffer byteBuffer, boolean fin, Callback callback) throws Throwable
{
- methodHandle.invoke(byteBuffer, fin);
+ methodHolder.invoke(byteBuffer, fin);
callback.succeeded();
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialStringMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialStringMessageSink.java
index ba74c2c5f13..cf34986cf59 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialStringMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/PartialStringMessageSink.java
@@ -13,13 +13,12 @@
package org.eclipse.jetty.websocket.core.messages;
-import java.lang.invoke.MethodHandle;
-
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Utf8StringBuilder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.exception.BadPayloadException;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
/**
*
A {@link MessageSink} implementation that delivers TEXT frames
@@ -34,12 +33,12 @@ public class PartialStringMessageSink extends AbstractMessageSink
* Creates a new {@link PartialStringMessageSink}.
*
* @param session the WebSocket session
- * @param methodHandle the application function to invoke when a new frame has arrived
+ * @param methodHolder the application function to invoke when a new frame has arrived
* @param autoDemand whether this {@link MessageSink} manages demand automatically
*/
- public PartialStringMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public PartialStringMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
- super(session, methodHandle, autoDemand);
+ super(session, methodHolder, autoDemand);
}
@Override
@@ -55,12 +54,12 @@ public class PartialStringMessageSink extends AbstractMessageSink
if (frame.isFin())
{
String complete = accumulator.takeCompleteString(BadPayloadException.InvalidUtf8::new);
- getMethodHandle().invoke(complete, true);
+ getMethodHolder().invoke(complete, true);
}
else
{
String partial = accumulator.takePartialString(BadPayloadException.InvalidUtf8::new);
- getMethodHandle().invoke(partial, false);
+ getMethodHolder().invoke(partial, false);
}
callback.succeeded();
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ReaderMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ReaderMessageSink.java
index 8f8e4f1759a..fb6cc87f1e7 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ReaderMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/ReaderMessageSink.java
@@ -13,15 +13,14 @@
package org.eclipse.jetty.websocket.core.messages;
-import java.lang.invoke.MethodHandle;
-
import org.eclipse.jetty.websocket.core.CoreSession;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class ReaderMessageSink extends DispatchedMessageSink
{
- public ReaderMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public ReaderMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
- super(session, methodHandle, autoDemand);
+ super(session, methodHolder, autoDemand);
}
@Override
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/StringMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/StringMessageSink.java
index e3bb1ded729..66fff19726e 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/StringMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/messages/StringMessageSink.java
@@ -13,14 +13,13 @@
package org.eclipse.jetty.websocket.core.messages;
-import java.lang.invoke.MethodHandle;
-
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Utf8StringBuilder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.exception.BadPayloadException;
import org.eclipse.jetty.websocket.core.exception.MessageTooLargeException;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
/**
*
A {@link MessageSink} implementation that accumulates TEXT frames
@@ -36,12 +35,12 @@ public class StringMessageSink extends AbstractMessageSink
* Creates a new {@link StringMessageSink}.
*
* @param session the WebSocket session
- * @param methodHandle the application function to invoke when a new message has been assembled
+ * @param methodHolder the application function to invoke when a new message has been assembled
* @param autoDemand whether this {@link MessageSink} manages demand automatically
*/
- public StringMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public StringMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
- super(session, methodHandle, autoDemand);
+ super(session, methodHolder, autoDemand);
this.size = 0;
}
@@ -64,7 +63,7 @@ public class StringMessageSink extends AbstractMessageSink
if (frame.isFin())
{
- getMethodHandle().invoke(out.takeCompleteString(BadPayloadException.InvalidUtf8::new));
+ getMethodHolder().invoke(out.takeCompleteString(BadPayloadException.InvalidUtf8::new));
reset();
callback.succeeded();
autoDemand();
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/InvokerUtils.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/InvokerUtils.java
index 6fc71474e63..e8a6e6c68e8 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/InvokerUtils.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/InvokerUtils.java
@@ -135,18 +135,18 @@ public class InvokerUtils
/**
* Bind optional arguments to provided method handle
*
- * @param methodHandle the method handle to bind to
+ * @param methodHolder the method handle to bind to
* @param objs the list of optional objects to bind to.
- * @return the bound MethodHandle, or null if the provided {@code methodHandle} was null.
+ * @return the bound MethodHandle, or null if the provided {@code methodHolder} was null.
*/
- public static MethodHandle bindTo(MethodHandle methodHandle, Object... objs)
+ public static MethodHolder bindTo(MethodHolder methodHolder, Object... objs)
{
- if (methodHandle == null)
+ if (methodHolder == null)
return null;
- MethodHandle ret = methodHandle;
+ MethodHolder ret = methodHolder;
for (Object obj : objs)
{
- if (ret.type().parameterType(0).isAssignableFrom(obj.getClass()))
+ if (ret.parameterType(0).isAssignableFrom(obj.getClass()))
{
ret = ret.bindTo(obj);
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/MethodHolder.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/MethodHolder.java
new file mode 100644
index 00000000000..6d81a90f209
--- /dev/null
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/MethodHolder.java
@@ -0,0 +1,230 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.core.util;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.WrongMethodTypeException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * An interface for managing invocations of methods whose arguments may need to be augmented, by
+ * binding in certain parameters ahead of time.
+ *
+ * Implementations may use various invocation mechanisms, including:
+ *
+ * - direct method invocation on an held object
+ * - calling a method pointer
+ * - calling a MethodHandle bound to the known arguments
+ * - calling a MethodHandle without binding to the known arguments
+ *
+ *
+ * Implementations of this may not be thread safe, so the caller must use some external mutual exclusion
+ * unless they are using a specific implementation known to be thread-safe.
+ */
+public interface MethodHolder
+{
+ String METHOD_HOLDER_BINDING_PROPERTY = "jetty.websocket.methodholder.binding";
+ boolean IS_BINDING = System.getProperty(METHOD_HOLDER_BINDING_PROPERTY) == null || Boolean.getBoolean(METHOD_HOLDER_BINDING_PROPERTY);
+
+ static MethodHolder from(MethodHandle methodHandle)
+ {
+ return from(methodHandle, IS_BINDING);
+ }
+
+ static MethodHolder from(MethodHandle methodHandle, boolean binding)
+ {
+ if (methodHandle == null)
+ return null;
+ return binding ? new Binding(methodHandle) : new NonBinding(methodHandle);
+ }
+
+ Object invoke(Object... args) throws Throwable;
+
+ default MethodHolder bindTo(Object arg)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ default MethodHolder bindTo(Object arg, int idx)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ default Class> parameterType(int idx)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ default Class> returnType()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ static Object doInvoke(MethodHandle methodHandle, Object... args) throws Throwable
+ {
+ switch (args.length)
+ {
+ case 0:
+ return methodHandle.invoke();
+ case 1:
+ return methodHandle.invoke(args[0]);
+ case 2:
+ return methodHandle.invoke(args[0], args[1]);
+ case 3:
+ return methodHandle.invoke(args[0], args[1], args[2]);
+ case 4:
+ return methodHandle.invoke(args[0], args[1], args[2], args[3]);
+ case 5:
+ return methodHandle.invoke(args[0], args[1], args[2], args[3], args[4]);
+ case 6:
+ return methodHandle.invoke(args[0], args[1], args[2], args[3], args[4], args[5]);
+ case 7:
+ return methodHandle.invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ case 8:
+ return methodHandle.invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
+ case 9:
+ return methodHandle.invoke(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]);
+ default:
+ return methodHandle.invokeWithArguments(args);
+ }
+ }
+
+ class Binding implements MethodHolder
+ {
+ public MethodHandle _methodHandle;
+
+ private Binding(MethodHandle methodHandle)
+ {
+ _methodHandle = methodHandle;
+ }
+
+ @Override
+ public Object invoke(Object... args) throws Throwable
+ {
+ return doInvoke(_methodHandle, args);
+ }
+
+ @Override
+ public Binding bindTo(Object arg)
+ {
+ _methodHandle = _methodHandle.bindTo(arg);
+ return this;
+ }
+
+ @Override
+ public MethodHolder bindTo(Object arg, int idx)
+ {
+ _methodHandle = MethodHandles.insertArguments(_methodHandle, idx, arg);
+ return this;
+ }
+
+ @Override
+ public Class> parameterType(int idx)
+ {
+ return _methodHandle.type().parameterType(idx);
+ }
+
+ @Override
+ public Class> returnType()
+ {
+ return _methodHandle.type().returnType();
+ }
+ }
+
+ /**
+ * This implementation of {@link MethodHolder} is not thread safe.
+ * Mutual exclusion should be used when calling {@link #invoke(Object...)}, or this should only
+ * be invoked from a single thread.
+ */
+ class NonBinding implements MethodHolder
+ {
+ private final MethodHandle _methodHandle;
+ private final Object[] _parameters;
+ private final List _unboundParamIndexes = new ArrayList<>();
+
+ private NonBinding(MethodHandle methodHandle)
+ {
+ _methodHandle = Objects.requireNonNull(methodHandle);
+ int numParams = methodHandle.type().parameterCount();
+ _parameters = new Object[numParams];
+ for (int i = 0; i < numParams; i++)
+ {
+ _unboundParamIndexes.add(i);
+ }
+ }
+
+ @Override
+ public Object invoke(Object... args) throws Throwable
+ {
+ try
+ {
+ insertArguments(args);
+ return doInvoke(_methodHandle, _parameters);
+ }
+ finally
+ {
+ clearArguments();
+ }
+ }
+
+ @Override
+ public MethodHolder bindTo(Object arg, int idx)
+ {
+ _parameters[_unboundParamIndexes.get(idx)] = arg;
+ _unboundParamIndexes.remove(idx);
+ return this;
+ }
+
+ @Override
+ public MethodHolder bindTo(Object arg)
+ {
+ return bindTo(arg, 0);
+ }
+
+ private void insertArguments(Object... args)
+ {
+ if (_unboundParamIndexes.size() != args.length)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", _unboundParamIndexes.size(), args.length));
+
+ int argsIndex = 0;
+ for (int index : _unboundParamIndexes)
+ {
+ _parameters[index] = args[argsIndex++];
+ }
+ }
+
+ private void clearArguments()
+ {
+ for (int i : _unboundParamIndexes)
+ {
+ _parameters[i] = null;
+ }
+ }
+
+ @Override
+ public Class> parameterType(int idx)
+ {
+ return _methodHandle.type().parameterType(_unboundParamIndexes.get(idx));
+ }
+
+ @Override
+ public Class> returnType()
+ {
+ return _methodHandle.type().returnType();
+ }
+ }
+}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/PartialStringMessageSinkTest.java b/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/PartialStringMessageSinkTest.java
index 80d6cd4302d..daa360a4822 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/PartialStringMessageSinkTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/PartialStringMessageSinkTest.java
@@ -51,7 +51,7 @@ public class PartialStringMessageSinkTest
@BeforeEach
public void before() throws Exception
{
- messageSink = new PartialStringMessageSink(coreSession, endpoint.getMethodHandle(), true);
+ messageSink = new PartialStringMessageSink(coreSession, MethodHolder.from(endpoint.getMethodHandle()), true);
}
@Test
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/StringMessageSinkTest.java b/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/StringMessageSinkTest.java
index a5448b74b45..69cbd26ece2 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/StringMessageSinkTest.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-tests/src/test/java/org/eclipse/jetty/websocket/core/util/StringMessageSinkTest.java
@@ -38,13 +38,13 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
public class StringMessageSinkTest
{
- private CoreSession coreSession = new CoreSession.Empty();
- private OnMessageEndpoint endpoint = new OnMessageEndpoint();
+ private final CoreSession coreSession = new CoreSession.Empty();
+ private final OnMessageEndpoint endpoint = new OnMessageEndpoint();
@Test
public void testMaxMessageSize() throws Exception
{
- StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle(), true);
+ StringMessageSink messageSink = new StringMessageSink(coreSession, MethodHolder.from(endpoint.getMethodHandle()), true);
ByteBuffer utf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0xF0, (byte)0x90, (byte)0x8D, (byte)0x88});
FutureCallback callback = new FutureCallback();
@@ -60,7 +60,7 @@ public class StringMessageSinkTest
@Test
public void testValidUtf8() throws Exception
{
- StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle(), true);
+ StringMessageSink messageSink = new StringMessageSink(coreSession, MethodHolder.from(endpoint.getMethodHandle()), true);
ByteBuffer utf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0xF0, (byte)0x90, (byte)0x8D, (byte)0x88});
FutureCallback callback = new FutureCallback();
@@ -73,7 +73,7 @@ public class StringMessageSinkTest
@Test
public void testUtf8Continuation() throws Exception
{
- StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle(), true);
+ StringMessageSink messageSink = new StringMessageSink(coreSession, MethodHolder.from(endpoint.getMethodHandle()), true);
ByteBuffer firstUtf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0xF0, (byte)0x90});
ByteBuffer continuationUtf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0x8D, (byte)0x88});
@@ -91,7 +91,7 @@ public class StringMessageSinkTest
@Test
public void testInvalidSingleFrameUtf8() throws Exception
{
- StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle(), true);
+ StringMessageSink messageSink = new StringMessageSink(coreSession, MethodHolder.from(endpoint.getMethodHandle()), true);
ByteBuffer invalidUtf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0xF0, (byte)0x90, (byte)0x8D});
FutureCallback callback = new FutureCallback();
@@ -106,7 +106,7 @@ public class StringMessageSinkTest
@Test
public void testInvalidMultiFrameUtf8() throws Exception
{
- StringMessageSink messageSink = new StringMessageSink(coreSession, endpoint.getMethodHandle(), true);
+ StringMessageSink messageSink = new StringMessageSink(coreSession, MethodHolder.from(endpoint.getMethodHandle()), true);
ByteBuffer firstUtf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0xF0, (byte)0x90});
ByteBuffer continuationUtf8Payload = BufferUtil.toBuffer(new byte[]{(byte)0x8D});
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandler.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandler.java
index d304ef864ad..902784fda5d 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandler.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandler.java
@@ -42,6 +42,7 @@ import org.eclipse.jetty.websocket.core.exception.WebSocketException;
import org.eclipse.jetty.websocket.core.exception.WebSocketTimeoutException;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,16 +53,16 @@ public class JettyWebSocketFrameHandler implements FrameHandler
private final WebSocketContainer container;
private final Object endpointInstance;
private final JettyWebSocketFrameHandlerMetadata metadata;
- private MethodHandle openHandle;
- private MethodHandle closeHandle;
- private MethodHandle errorHandle;
- private MethodHandle textHandle;
- private MethodHandle binaryHandle;
+ private MethodHolder openHandle;
+ private MethodHolder closeHandle;
+ private MethodHolder errorHandle;
+ private MethodHolder textHandle;
+ private MethodHolder binaryHandle;
private final Class extends MessageSink> textSinkClass;
private final Class extends MessageSink> binarySinkClass;
- private MethodHandle frameHandle;
- private MethodHandle pingHandle;
- private MethodHandle pongHandle;
+ private MethodHolder frameHandle;
+ private MethodHolder pingHandle;
+ private MethodHolder pongHandle;
private UpgradeRequest upgradeRequest;
private UpgradeResponse upgradeResponse;
private MessageSink textSink;
@@ -76,16 +77,16 @@ public class JettyWebSocketFrameHandler implements FrameHandler
this.endpointInstance = endpointInstance;
this.metadata = metadata;
- this.openHandle = InvokerUtils.bindTo(metadata.getOpenHandle(), endpointInstance);
- this.closeHandle = InvokerUtils.bindTo(metadata.getCloseHandle(), endpointInstance);
- this.errorHandle = InvokerUtils.bindTo(metadata.getErrorHandle(), endpointInstance);
- this.textHandle = InvokerUtils.bindTo(metadata.getTextHandle(), endpointInstance);
- this.binaryHandle = InvokerUtils.bindTo(metadata.getBinaryHandle(), endpointInstance);
+ this.openHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getOpenHandle()), endpointInstance);
+ this.closeHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getCloseHandle()), endpointInstance);
+ this.errorHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getErrorHandle()), endpointInstance);
+ this.textHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getTextHandle()), endpointInstance);
+ this.binaryHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getBinaryHandle()), endpointInstance);
this.textSinkClass = metadata.getTextSink();
this.binarySinkClass = metadata.getBinarySink();
- this.frameHandle = InvokerUtils.bindTo(metadata.getFrameHandle(), endpointInstance);
- this.pingHandle = InvokerUtils.bindTo(metadata.getPingHandle(), endpointInstance);
- this.pongHandle = InvokerUtils.bindTo(metadata.getPongHandle(), endpointInstance);
+ this.frameHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getFrameHandle()), endpointInstance);
+ this.pingHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getPingHandle()), endpointInstance);
+ this.pongHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getPongHandle()), endpointInstance);
}
public void setUpgradeRequest(UpgradeRequest upgradeRequest)
@@ -157,7 +158,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
}
}
- private static MessageSink createMessageSink(Class extends MessageSink> sinkClass, WebSocketSession session, MethodHandle msgHandle, boolean autoDemanding)
+ private static MessageSink createMessageSink(Class extends MessageSink> sinkClass, WebSocketSession session, MethodHolder msgHandle, boolean autoDemanding)
{
if (msgHandle == null)
return null;
@@ -168,7 +169,7 @@ public class JettyWebSocketFrameHandler implements FrameHandler
{
MethodHandles.Lookup lookup = JettyWebSocketFrameHandlerFactory.getServerMethodHandleLookup();
MethodHandle ctorHandle = lookup.findConstructor(sinkClass,
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, boolean.class));
+ MethodType.methodType(void.class, CoreSession.class, MethodHolder.class, boolean.class));
return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgHandle, autoDemanding);
}
catch (NoSuchMethodException e)
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/ByteBufferMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/ByteBufferMessageSink.java
index 4d9b6b3ef26..7eadef8f20b 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/ByteBufferMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/ByteBufferMessageSink.java
@@ -13,28 +13,22 @@
package org.eclipse.jetty.websocket.common.internal;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.core.CoreSession;
-import org.eclipse.jetty.websocket.core.exception.InvalidSignatureException;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class ByteBufferMessageSink extends org.eclipse.jetty.websocket.core.messages.ByteBufferMessageSink
{
- public ByteBufferMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public ByteBufferMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
- super(session, methodHandle, autoDemand, false);
-
- MethodType onMessageType = MethodType.methodType(Void.TYPE, ByteBuffer.class, Callback.class);
- if (methodHandle.type() != onMessageType)
- throw InvalidSignatureException.build(onMessageType, methodHandle.type());
+ super(session, methodHolder, autoDemand);
}
@Override
- protected void invoke(MethodHandle methodHandle, ByteBuffer byteBuffer, org.eclipse.jetty.util.Callback callback) throws Throwable
+ protected void invoke(MethodHolder methodHolder, ByteBuffer byteBuffer, org.eclipse.jetty.util.Callback callback) throws Throwable
{
- methodHandle.invoke(byteBuffer, Callback.from(callback::succeeded, callback::failed));
+ methodHolder.invoke(byteBuffer, Callback.from(callback::succeeded, callback::failed));
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/PartialByteBufferMessageSink.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/PartialByteBufferMessageSink.java
index 479e90cb779..04a524e58fa 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/PartialByteBufferMessageSink.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/internal/PartialByteBufferMessageSink.java
@@ -13,28 +13,22 @@
package org.eclipse.jetty.websocket.common.internal;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;
import org.eclipse.jetty.websocket.api.Callback;
import org.eclipse.jetty.websocket.core.CoreSession;
-import org.eclipse.jetty.websocket.core.exception.InvalidSignatureException;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class PartialByteBufferMessageSink extends org.eclipse.jetty.websocket.core.messages.PartialByteBufferMessageSink
{
- public PartialByteBufferMessageSink(CoreSession session, MethodHandle methodHandle, boolean autoDemand)
+ public PartialByteBufferMessageSink(CoreSession session, MethodHolder methodHolder, boolean autoDemand)
{
- super(session, methodHandle, autoDemand);
-
- MethodType onMessageType = MethodType.methodType(Void.TYPE, ByteBuffer.class, boolean.class, Callback.class);
- if (methodHandle.type() != onMessageType)
- throw InvalidSignatureException.build(onMessageType, methodHandle.type());
+ super(session, methodHolder, autoDemand);
}
@Override
- protected void invoke(MethodHandle methodHandle, ByteBuffer byteBuffer, boolean fin, org.eclipse.jetty.util.Callback callback) throws Throwable
+ protected void invoke(MethodHolder methodHolder, ByteBuffer byteBuffer, boolean fin, org.eclipse.jetty.util.Callback callback) throws Throwable
{
- methodHandle.invoke(byteBuffer, fin, Callback.from(callback::succeeded, callback::failed));
+ methodHolder.invoke(byteBuffer, fin, Callback.from(callback::succeeded, callback::failed));
}
}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingMessageCapture.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingMessageCapture.java
index 206eb603937..cb9edd2c9ad 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingMessageCapture.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/test/java/org/eclipse/jetty/websocket/common/OutgoingMessageCapture.java
@@ -31,6 +31,7 @@ import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
import org.eclipse.jetty.websocket.core.messages.StringMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -96,7 +97,7 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
String event = String.format("TEXT:fin=%b:len=%d", frame.isFin(), frame.getPayloadLength());
LOG.debug(event);
events.offer(event);
- messageSink = new StringMessageSink(this, wholeTextHandle, true);
+ messageSink = new StringMessageSink(this, MethodHolder.from(wholeTextHandle), true);
break;
}
case OpCode.BINARY:
@@ -104,7 +105,7 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
String event = String.format("BINARY:fin=%b:len=%d", frame.isFin(), frame.getPayloadLength());
LOG.debug(event);
events.offer(event);
- messageSink = new ByteBufferMessageSink(this, wholeBinaryHandle, true);
+ messageSink = new ByteBufferMessageSink(this, MethodHolder.from(wholeBinaryHandle), true);
break;
}
case OpCode.CONTINUATION:
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaMessagePartialMethodHolder.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaMessagePartialMethodHolder.java
new file mode 100644
index 00000000000..7b3e66f1849
--- /dev/null
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaMessagePartialMethodHolder.java
@@ -0,0 +1,59 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.ee10.websocket.jakarta.common;
+
+import java.lang.invoke.WrongMethodTypeException;
+
+import jakarta.websocket.MessageHandler;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
+
+class JakartaMessagePartialMethodHolder implements MethodHolder
+{
+ private final MessageHandler.Partial _messageHandler;
+
+ public JakartaMessagePartialMethodHolder(MessageHandler.Partial messageHandler)
+ {
+ _messageHandler = messageHandler;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object invoke(Object... args) throws Throwable
+ {
+ if (args.length != 2)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 2, args.length));
+ _messageHandler.onMessage((T)args[0], (boolean)args[1]);
+ return null;
+ }
+
+ @Override
+ public Class> parameterType(int idx)
+ {
+ switch (idx)
+ {
+ case 0:
+ return Object.class;
+ case 1:
+ return boolean.class;
+ default:
+ throw new IndexOutOfBoundsException(idx);
+ }
+ }
+
+ @Override
+ public Class> returnType()
+ {
+ return void.class;
+ }
+}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaMessageWholeMethodHolder.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaMessageWholeMethodHolder.java
new file mode 100644
index 00000000000..efe8bab30a8
--- /dev/null
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaMessageWholeMethodHolder.java
@@ -0,0 +1,57 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.ee10.websocket.jakarta.common;
+
+import java.lang.invoke.WrongMethodTypeException;
+
+import jakarta.websocket.MessageHandler;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
+
+class JakartaMessageWholeMethodHolder implements MethodHolder
+{
+ private final MessageHandler.Whole _messageHandler;
+
+ public JakartaMessageWholeMethodHolder(MessageHandler.Whole messageHandler)
+ {
+ _messageHandler = messageHandler;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object invoke(Object... args) throws Throwable
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ _messageHandler.onMessage((T)args[0]);
+ return null;
+ }
+
+ @Override
+ public Class> parameterType(int idx)
+ {
+ switch (idx)
+ {
+ case 0:
+ return Object.class;
+ default:
+ throw new IndexOutOfBoundsException(idx);
+ }
+ }
+
+ @Override
+ public Class> returnType()
+ {
+ return void.class;
+ }
+}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandler.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
index 86f110b4ed6..a04015b94cf 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
@@ -13,8 +13,6 @@
package org.eclipse.jetty.ee10.websocket.jakarta.common;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
@@ -51,6 +49,7 @@ import org.eclipse.jetty.websocket.core.messages.PartialByteArrayMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialStringMessageSink;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,10 +61,10 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
private final Object endpointInstance;
private final AtomicBoolean closeNotified = new AtomicBoolean();
- private MethodHandle openHandle;
- private MethodHandle closeHandle;
- private MethodHandle errorHandle;
- private MethodHandle pongHandle;
+ private MethodHolder openHandle;
+ private MethodHolder closeHandle;
+ private MethodHolder errorHandle;
+ private MethodHolder pongHandle;
private JakartaWebSocketMessageMetadata textMetadata;
private JakartaWebSocketMessageMetadata binaryMetadata;
private final UpgradeRequest upgradeRequest;
@@ -79,12 +78,12 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
protected byte dataType = OpCode.UNDEFINED;
public JakartaWebSocketFrameHandler(JakartaWebSocketContainer container,
- UpgradeRequest upgradeRequest,
+ UpgradeRequest upgradeRequest,
Object endpointInstance,
- MethodHandle openHandle, MethodHandle closeHandle, MethodHandle errorHandle,
- JakartaWebSocketMessageMetadata textMetadata,
- JakartaWebSocketMessageMetadata binaryMetadata,
- MethodHandle pongHandle,
+ MethodHolder openHandle, MethodHolder closeHandle, MethodHolder errorHandle,
+ JakartaWebSocketMessageMetadata textMetadata,
+ JakartaWebSocketMessageMetadata binaryMetadata,
+ MethodHolder pongHandle,
EndpointConfig endpointConfig)
{
this.logger = LoggerFactory.getLogger(endpointInstance.getClass());
@@ -147,10 +146,10 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
if (actualTextMetadata.isMaxMessageSizeSet())
session.setMaxTextMessageBufferSize(actualTextMetadata.getMaxMessageSize());
- MethodHandle methodHandle = actualTextMetadata.getMethodHandle();
- methodHandle = InvokerUtils.bindTo(methodHandle, endpointInstance, endpointConfig, session);
- methodHandle = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHandle, session);
- actualTextMetadata.setMethodHandle(methodHandle);
+ MethodHolder methodHolder = actualTextMetadata.getMethodHolder();
+ methodHolder = InvokerUtils.bindTo(methodHolder, endpointInstance, endpointConfig, session);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHolder, session);
+ actualTextMetadata.setMethodHolder(methodHolder);
textSink = JakartaWebSocketFrameHandlerFactory.createMessageSink(session, actualTextMetadata);
textMetadata = actualTextMetadata;
@@ -162,10 +161,10 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
if (actualBinaryMetadata.isMaxMessageSizeSet())
session.setMaxBinaryMessageBufferSize(actualBinaryMetadata.getMaxMessageSize());
- MethodHandle methodHandle = actualBinaryMetadata.getMethodHandle();
- methodHandle = InvokerUtils.bindTo(methodHandle, endpointInstance, endpointConfig, session);
- methodHandle = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHandle, session);
- actualBinaryMetadata.setMethodHandle(methodHandle);
+ MethodHolder methodHolder = actualBinaryMetadata.getMethodHolder();
+ methodHolder = InvokerUtils.bindTo(methodHolder, endpointInstance, endpointConfig, session);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHolder, session);
+ actualBinaryMetadata.setMethodHolder(methodHolder);
binarySink = JakartaWebSocketFrameHandlerFactory.createMessageSink(session, actualBinaryMetadata);
binaryMetadata = actualBinaryMetadata;
@@ -346,116 +345,88 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
public void addMessageHandler(Class clazz, MessageHandler.Partial handler)
{
- try
+ JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
+ metadata.setMethodHolder(new JakartaMessagePartialMethodHolder<>(handler));
+ byte basicType;
+ // MessageHandler.Partial has no decoder support!
+ if (byte[].class.isAssignableFrom(clazz))
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(MessageHandler.Partial.class, "onMessage", MethodType.methodType(void.class, Object.class, boolean.class))
- .bindTo(handler);
+ basicType = OpCode.BINARY;
+ metadata.setSinkClass(PartialByteArrayMessageSink.class);
+ }
+ else if (ByteBuffer.class.isAssignableFrom(clazz))
+ {
+ basicType = OpCode.BINARY;
+ metadata.setSinkClass(PartialByteBufferMessageSink.class);
+ }
+ else if (String.class.isAssignableFrom(clazz))
+ {
+ basicType = OpCode.TEXT;
+ metadata.setSinkClass(PartialStringMessageSink.class);
+ }
+ else
+ {
+ throw new RuntimeException(
+ "Unable to add " + handler.getClass().getName() + " with type " + clazz + ": only supported types byte[], " + ByteBuffer.class.getName() +
+ ", " + String.class.getName());
+ }
- JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
- metadata.setMethodHandle(methodHandle);
- byte basicType;
- // MessageHandler.Partial has no decoder support!
- if (byte[].class.isAssignableFrom(clazz))
- {
- basicType = OpCode.BINARY;
- metadata.setSinkClass(PartialByteArrayMessageSink.class);
- }
- else if (ByteBuffer.class.isAssignableFrom(clazz))
- {
- basicType = OpCode.BINARY;
- metadata.setSinkClass(PartialByteBufferMessageSink.class);
- }
- else if (String.class.isAssignableFrom(clazz))
- {
- basicType = OpCode.TEXT;
- metadata.setSinkClass(PartialStringMessageSink.class);
- }
- else
- {
- throw new RuntimeException(
- "Unable to add " + handler.getClass().getName() + " with type " + clazz + ": only supported types byte[], " + ByteBuffer.class.getName() +
- ", " + String.class.getName());
- }
-
- // Register the Metadata as a MessageHandler.
- registerMessageHandler(clazz, handler, basicType, metadata);
- }
- catch (NoSuchMethodException e)
- {
- throw new IllegalStateException("Unable to find method", e);
- }
- catch (IllegalAccessException e)
- {
- throw new IllegalStateException("Unable to access " + handler.getClass().getName(), e);
- }
+ // Register the Metadata as a MessageHandler.
+ registerMessageHandler(clazz, handler, basicType, metadata);
}
public void addMessageHandler(Class clazz, MessageHandler.Whole handler)
{
- try
+ MethodHolder methodHolder = new JakartaMessageWholeMethodHolder<>(handler);
+
+ if (PongMessage.class.isAssignableFrom(clazz))
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(MessageHandler.Whole.class, "onMessage", MethodType.methodType(void.class, Object.class))
- .bindTo(handler);
-
- if (PongMessage.class.isAssignableFrom(clazz))
- {
- assertBasicTypeNotRegistered(OpCode.PONG, handler);
- this.pongHandle = methodHandle;
- registerMessageHandler(OpCode.PONG, clazz, handler, null);
- return;
- }
-
- AvailableDecoders availableDecoders = session.getDecoders();
- RegisteredDecoder registeredDecoder = availableDecoders.getFirstRegisteredDecoder(clazz);
- if (registeredDecoder == null)
- throw new IllegalStateException("Unable to find Decoder for type: " + clazz);
-
- // Create the message metadata specific to the MessageHandler type.
- JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
- metadata.setMethodHandle(methodHandle);
- byte basicType;
- if (registeredDecoder.implementsInterface(Decoder.Binary.class))
- {
- basicType = OpCode.BINARY;
- metadata.setRegisteredDecoders(availableDecoders.getBinaryDecoders(clazz));
- metadata.setSinkClass(DecodedBinaryMessageSink.class);
- }
- else if (registeredDecoder.implementsInterface(Decoder.BinaryStream.class))
- {
- basicType = OpCode.BINARY;
- metadata.setRegisteredDecoders(availableDecoders.getBinaryStreamDecoders(clazz));
- metadata.setSinkClass(DecodedBinaryStreamMessageSink.class);
- }
- else if (registeredDecoder.implementsInterface(Decoder.Text.class))
- {
- basicType = OpCode.TEXT;
- metadata.setRegisteredDecoders(availableDecoders.getTextDecoders(clazz));
- metadata.setSinkClass(DecodedTextMessageSink.class);
- }
- else if (registeredDecoder.implementsInterface(Decoder.TextStream.class))
- {
- basicType = OpCode.TEXT;
- metadata.setRegisteredDecoders(availableDecoders.getTextStreamDecoders(clazz));
- metadata.setSinkClass(DecodedTextStreamMessageSink.class);
- }
- else
- {
- throw new RuntimeException("Unable to add " + handler.getClass().getName() + ": type " + clazz + " is unrecognized by declared decoders");
- }
-
- // Register the Metadata as a MessageHandler.
- registerMessageHandler(clazz, handler, basicType, metadata);
+ assertBasicTypeNotRegistered(OpCode.PONG, handler);
+ this.pongHandle = methodHolder;
+ registerMessageHandler(OpCode.PONG, clazz, handler, null);
+ return;
}
- catch (NoSuchMethodException e)
+
+ AvailableDecoders availableDecoders = session.getDecoders();
+ RegisteredDecoder registeredDecoder = availableDecoders.getFirstRegisteredDecoder(clazz);
+ if (registeredDecoder == null)
+ throw new IllegalStateException("Unable to find Decoder for type: " + clazz);
+
+ // Create the message metadata specific to the MessageHandler type.
+ JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
+ metadata.setMethodHolder(methodHolder);
+ byte basicType;
+ if (registeredDecoder.implementsInterface(Decoder.Binary.class))
{
- throw new IllegalStateException("Unable to find method", e);
+ basicType = OpCode.BINARY;
+ metadata.setRegisteredDecoders(availableDecoders.getBinaryDecoders(clazz));
+ metadata.setSinkClass(DecodedBinaryMessageSink.class);
}
- catch (IllegalAccessException e)
+ else if (registeredDecoder.implementsInterface(Decoder.BinaryStream.class))
{
- throw new IllegalStateException("Unable to access " + handler.getClass().getName(), e);
+ basicType = OpCode.BINARY;
+ metadata.setRegisteredDecoders(availableDecoders.getBinaryStreamDecoders(clazz));
+ metadata.setSinkClass(DecodedBinaryStreamMessageSink.class);
}
+ else if (registeredDecoder.implementsInterface(Decoder.Text.class))
+ {
+ basicType = OpCode.TEXT;
+ metadata.setRegisteredDecoders(availableDecoders.getTextDecoders(clazz));
+ metadata.setSinkClass(DecodedTextMessageSink.class);
+ }
+ else if (registeredDecoder.implementsInterface(Decoder.TextStream.class))
+ {
+ basicType = OpCode.TEXT;
+ metadata.setRegisteredDecoders(availableDecoders.getTextStreamDecoders(clazz));
+ metadata.setSinkClass(DecodedTextStreamMessageSink.class);
+ }
+ else
+ {
+ throw new RuntimeException("Unable to add " + handler.getClass().getName() + ": type " + clazz + " is unrecognized by declared decoders");
+ }
+
+ // Register the Metadata as a MessageHandler.
+ registerMessageHandler(clazz, handler, basicType, metadata);
}
private void assertBasicTypeNotRegistered(byte basicWebSocketType, MessageHandler replacement)
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
index dd90ab38a13..afd8f383282 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
@@ -52,6 +52,7 @@ import org.eclipse.jetty.websocket.core.messages.PartialByteArrayMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialStringMessageSink;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.eclipse.jetty.websocket.core.util.ReflectUtils;
public abstract class JakartaWebSocketFrameHandlerFactory
@@ -135,10 +136,10 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (metadata == null)
return null;
- MethodHandle openHandle = metadata.getOpenHandle();
- MethodHandle closeHandle = metadata.getCloseHandle();
- MethodHandle errorHandle = metadata.getErrorHandle();
- MethodHandle pongHandle = metadata.getPongHandle();
+ MethodHolder openHandle = MethodHolder.from(metadata.getOpenHandle());
+ MethodHolder closeHandle = MethodHolder.from(metadata.getCloseHandle());
+ MethodHolder errorHandle = MethodHolder.from(metadata.getErrorHandle());
+ MethodHolder pongHandle = MethodHolder.from(metadata.getPongHandle());
JakartaWebSocketMessageMetadata textMetadata = JakartaWebSocketMessageMetadata.copyOf(metadata.getTextMetadata());
JakartaWebSocketMessageMetadata binaryMetadata = JakartaWebSocketMessageMetadata.copyOf(metadata.getBinaryMetadata());
@@ -156,9 +157,9 @@ public abstract class JakartaWebSocketFrameHandlerFactory
pongHandle = bindTemplateVariables(pongHandle, namedVariables, pathParams);
if (textMetadata != null)
- textMetadata.setMethodHandle(bindTemplateVariables(textMetadata.getMethodHandle(), namedVariables, pathParams));
+ textMetadata.setMethodHolder(bindTemplateVariables(textMetadata.getMethodHolder(), namedVariables, pathParams));
if (binaryMetadata != null)
- binaryMetadata.setMethodHandle(bindTemplateVariables(binaryMetadata.getMethodHandle(), namedVariables, pathParams));
+ binaryMetadata.setMethodHolder(bindTemplateVariables(binaryMetadata.getMethodHolder(), namedVariables, pathParams));
}
openHandle = InvokerUtils.bindTo(openHandle, endpoint);
@@ -190,15 +191,15 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (AbstractDecodedMessageSink.class.isAssignableFrom(msgMetadata.getSinkClass()))
{
MethodHandle ctorHandle = lookup.findConstructor(msgMetadata.getSinkClass(),
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, List.class));
+ MethodType.methodType(void.class, CoreSession.class, MethodHolder.class, List.class));
List registeredDecoders = msgMetadata.getRegisteredDecoders();
- return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHandle(), registeredDecoders);
+ return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHolder(), registeredDecoders);
}
else
{
MethodHandle ctorHandle = lookup.findConstructor(msgMetadata.getSinkClass(),
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, boolean.class));
- return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHandle(), true);
+ MethodType.methodType(void.class, CoreSession.class, MethodHolder.class, boolean.class));
+ return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHolder(), true);
}
}
catch (NoSuchMethodException e)
@@ -219,23 +220,19 @@ public abstract class JakartaWebSocketFrameHandlerFactory
}
}
- public static MethodHandle wrapNonVoidReturnType(MethodHandle handle, JakartaWebSocketSession session)
+ public static MethodHolder wrapNonVoidReturnType(MethodHolder handle, JakartaWebSocketSession session)
{
if (handle == null)
return null;
- if (handle.type().returnType() == Void.TYPE)
+ if (handle.returnType() == Void.TYPE)
return handle;
- // Technique from https://stackoverflow.com/questions/48505787/methodhandle-with-general-non-void-return-filter
-
- // Change the return type of the to be Object so it will match exact with JakartaWebSocketSession.filterReturnType(Object)
- handle = handle.asType(handle.type().changeReturnType(Object.class));
-
- // Filter the method return type to a call to JakartaWebSocketSession.filterReturnType() bound to this session
- handle = MethodHandles.filterReturnValue(handle, FILTER_RETURN_TYPE_METHOD.bindTo(session));
-
- return handle;
+ return args ->
+ {
+ session.filterReturnType(handle.invoke(args));
+ return null;
+ };
}
private MethodHandle toMethodHandle(MethodHandles.Lookup lookup, Method method)
@@ -360,7 +357,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (methodHandle != null)
{
msgMetadata.setSinkClass(PartialStringMessageSink.class);
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
metadata.setTextMetadata(msgMetadata, onMsg);
return true;
}
@@ -370,7 +367,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (methodHandle != null)
{
msgMetadata.setSinkClass(PartialByteBufferMessageSink.class);
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
metadata.setBinaryMetadata(msgMetadata, onMsg);
return true;
}
@@ -380,7 +377,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (methodHandle != null)
{
msgMetadata.setSinkClass(PartialByteArrayMessageSink.class);
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
metadata.setBinaryMetadata(msgMetadata, onMsg);
return true;
}
@@ -423,7 +420,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
objectType = decoder.objectType;
}
MethodHandle methodHandle = getMethodHandle.apply(getArgsFor(objectType));
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
// Set the sinkClass and then set the MessageMetadata on the FrameHandlerMetadata
if (interfaceType.equals(Decoder.Text.class))
@@ -508,7 +505,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
* have been statically assigned a converted value (and removed from the resulting {@link MethodHandle#type()}, or null if
* no {@code target} MethodHandle was provided.
*/
- public static MethodHandle bindTemplateVariables(MethodHandle target, String[] namedVariables, Map templateValues)
+ public static MethodHolder bindTemplateVariables(MethodHolder target, String[] namedVariables, Map templateValues)
{
if (target == null)
{
@@ -517,7 +514,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
final int IDX = 1;
- MethodHandle retHandle = target;
+ MethodHolder retHandle = target;
if ((templateValues == null) || (templateValues.isEmpty()))
{
@@ -527,54 +524,54 @@ public abstract class JakartaWebSocketFrameHandlerFactory
for (String variableName : namedVariables)
{
String strValue = templateValues.get(variableName);
- Class> type = retHandle.type().parameterType(IDX);
+ Class> type = retHandle.parameterType(IDX);
try
{
if (String.class.isAssignableFrom(type))
{
- retHandle = MethodHandles.insertArguments(retHandle, IDX, strValue);
+ retHandle = retHandle.bindTo(strValue, IDX);
}
else if (Integer.class.isAssignableFrom(type) || Integer.TYPE.isAssignableFrom(type))
{
Integer intValue = Integer.parseInt(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, intValue);
+ retHandle = retHandle.bindTo(intValue, IDX);
}
else if (Long.class.isAssignableFrom(type) || Long.TYPE.isAssignableFrom(type))
{
Long longValue = Long.parseLong(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, longValue);
+ retHandle = retHandle.bindTo(longValue, IDX);
}
else if (Short.class.isAssignableFrom(type) || Short.TYPE.isAssignableFrom(type))
{
Short shortValue = Short.parseShort(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, shortValue);
+ retHandle = retHandle.bindTo(shortValue, IDX);
}
else if (Float.class.isAssignableFrom(type) || Float.TYPE.isAssignableFrom(type))
{
Float floatValue = Float.parseFloat(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, floatValue);
+ retHandle = retHandle.bindTo(floatValue, IDX);
}
else if (Double.class.isAssignableFrom(type) || Double.TYPE.isAssignableFrom(type))
{
Double doubleValue = Double.parseDouble(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, doubleValue);
+ retHandle = retHandle.bindTo(doubleValue, IDX);
}
else if (Boolean.class.isAssignableFrom(type) || Boolean.TYPE.isAssignableFrom(type))
{
Boolean boolValue = Boolean.parseBoolean(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, boolValue);
+ retHandle = retHandle.bindTo(boolValue, IDX);
}
else if (Character.class.isAssignableFrom(type) || Character.TYPE.isAssignableFrom(type))
{
if (strValue.length() != 1)
throw new IllegalArgumentException("Invalid Size");
Character charValue = strValue.charAt(0);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, charValue);
+ retHandle = retHandle.bindTo(charValue, IDX);
}
else if (Byte.class.isAssignableFrom(type) || Byte.TYPE.isAssignableFrom(type))
{
Byte b = Byte.parseByte(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, b);
+ retHandle = retHandle.bindTo(b, IDX);
}
else
{
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java
index a5587ae30ae..7511f372e8c 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java
@@ -13,15 +13,15 @@
package org.eclipse.jetty.ee10.websocket.jakarta.common;
-import java.lang.invoke.MethodHandle;
import java.util.List;
import org.eclipse.jetty.ee10.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class JakartaWebSocketMessageMetadata
{
- private MethodHandle methodHandle;
+ private MethodHolder methodHolder;
private Class extends MessageSink> sinkClass;
private List registeredDecoders;
@@ -34,7 +34,7 @@ public class JakartaWebSocketMessageMetadata
return null;
JakartaWebSocketMessageMetadata copy = new JakartaWebSocketMessageMetadata();
- copy.methodHandle = metadata.methodHandle;
+ copy.methodHolder = metadata.methodHolder;
copy.sinkClass = metadata.sinkClass;
copy.registeredDecoders = metadata.registeredDecoders;
copy.maxMessageSize = metadata.maxMessageSize;
@@ -58,14 +58,14 @@ public class JakartaWebSocketMessageMetadata
this.maxMessageSizeSet = true;
}
- public MethodHandle getMethodHandle()
+ public MethodHolder getMethodHolder()
{
- return methodHandle;
+ return methodHolder;
}
- public void setMethodHandle(MethodHandle methodHandle)
+ public void setMethodHolder(MethodHolder methodHandle)
{
- this.methodHandle = methodHandle;
+ this.methodHolder = methodHandle;
}
public Class extends MessageSink> getSinkClass()
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java
index a62d243fb89..5c24767ae58 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java
@@ -13,7 +13,6 @@
package org.eclipse.jetty.ee10.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
import java.util.List;
import java.util.stream.Collectors;
@@ -25,6 +24,7 @@ import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,12 +32,12 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
private static final Logger LOG = LoggerFactory.getLogger(AbstractDecodedMessageSink.class);
- private final MethodHandle _methodHandle;
+ private final MethodHolder _methodHolder;
private final MessageSink _messageSink;
- public AbstractDecodedMessageSink(CoreSession coreSession, MethodHandle methodHandle)
+ public AbstractDecodedMessageSink(CoreSession coreSession, MethodHolder methodHolder)
{
- _methodHandle = methodHandle;
+ _methodHolder = methodHolder;
try
{
@@ -58,7 +58,7 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
try
{
- _methodHandle.invoke(message);
+ _methodHolder.invoke(message);
}
catch (Throwable t)
{
@@ -67,7 +67,7 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
}
/**
- * @return a message sink which will first decode the message then pass it to {@link #_methodHandle}.
+ * @return a message sink which will first decode the message then pass it to {@link #_methodHolder}.
* @throws Exception for any error in creating the message sink.
*/
abstract MessageSink newMessageSink(CoreSession coreSession) throws Exception;
@@ -90,9 +90,9 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
protected final List _decoders;
- public Basic(CoreSession coreSession, MethodHandle methodHandle, List decoders)
+ public Basic(CoreSession coreSession, MethodHolder methodHolder, List decoders)
{
- super(coreSession, methodHandle);
+ super(coreSession, methodHolder);
if (decoders.isEmpty())
throw new IllegalArgumentException("Require at least one decoder for " + this.getClass());
_decoders = decoders.stream()
@@ -105,9 +105,9 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
protected final T _decoder;
- public Stream(CoreSession coreSession, MethodHandle methodHandle, List decoders)
+ public Stream(CoreSession coreSession, MethodHolder methodHolder, List decoders)
{
- super(coreSession, methodHandle);
+ super(coreSession, methodHolder);
if (decoders.size() != 1)
throw new IllegalArgumentException("Require exactly one decoder for " + this.getClass());
_decoder = decoders.get(0).getInstance();
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
index d3715baf894..28b7b8c1924 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
@@ -13,20 +13,19 @@
package org.eclipse.jetty.ee10.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.nio.ByteBuffer;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee10.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee10.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.ByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,18 +33,23 @@ public class DecodedBinaryMessageSink extends AbstractDecodedMessageSink.Basi
{
private static final Logger LOG = LoggerFactory.getLogger(DecodedBinaryMessageSink.class);
- public DecodedBinaryMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedBinaryMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
- MessageSink newMessageSink(CoreSession coreSession) throws Exception
+ MessageSink newMessageSink(CoreSession coreSession)
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(DecodedBinaryMessageSink.class, "onWholeMessage", MethodType.methodType(void.class, ByteBuffer.class))
- .bindTo(this);
- return new ByteBufferMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onWholeMessage((ByteBuffer)args[0]);
+ return null;
+ };
+
+ return new ByteBufferMessageSink(coreSession, methodHolder, true);
}
public void onWholeMessage(ByteBuffer wholeMessage)
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
index 6e7b34c3ce0..ff699ae2c89 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
@@ -15,34 +15,38 @@ package org.eclipse.jetty.ee10.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee10.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee10.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.InputStreamMessageSink;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class DecodedBinaryStreamMessageSink extends AbstractDecodedMessageSink.Stream>
{
- public DecodedBinaryStreamMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedBinaryStreamMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
- MessageSink newMessageSink(CoreSession coreSession) throws Exception
+ MessageSink newMessageSink(CoreSession coreSession)
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(DecodedBinaryStreamMessageSink.class, "onStreamStart", MethodType.methodType(void.class, InputStream.class))
- .bindTo(this);
- return new InputStreamMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onStreamStart((InputStream)args[0]);
+ return null;
+ };
+
+ return new InputStreamMessageSink(coreSession, methodHolder, true);
}
public void onStreamStart(InputStream stream)
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSink.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSink.java
index 6b9f98b6b13..a6db6771b77 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSink.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSink.java
@@ -13,19 +13,18 @@
package org.eclipse.jetty.ee10.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee10.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee10.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
import org.eclipse.jetty.websocket.core.messages.StringMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,18 +32,23 @@ public class DecodedTextMessageSink extends AbstractDecodedMessageSink.Basic<
{
private static final Logger LOG = LoggerFactory.getLogger(DecodedTextMessageSink.class);
- public DecodedTextMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedTextMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
- MessageSink newMessageSink(CoreSession coreSession) throws NoSuchMethodException, IllegalAccessException
+ MessageSink newMessageSink(CoreSession coreSession)
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(getClass(), "onMessage", MethodType.methodType(void.class, String.class))
- .bindTo(this);
- return new StringMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onMessage((String)args[0]);
+ return null;
+ };
+
+ return new StringMessageSink(coreSession, methodHolder, true);
}
public void onMessage(String wholeMessage)
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
index 59bed6e8b85..2c8d2909cae 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
@@ -15,34 +15,38 @@ package org.eclipse.jetty.ee10.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.Reader;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee10.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee10.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
import org.eclipse.jetty.websocket.core.messages.ReaderMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class DecodedTextStreamMessageSink extends AbstractDecodedMessageSink.Stream>
{
- public DecodedTextStreamMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedTextStreamMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
- MessageSink newMessageSink(CoreSession coreSession) throws Exception
+ MessageSink newMessageSink(CoreSession coreSession)
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(DecodedTextStreamMessageSink.class, "onStreamStart", MethodType.methodType(void.class, Reader.class))
- .bindTo(this);
- return new ReaderMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onStreamStart((Reader)args[0]);
+ return null;
+ };
+
+ return new ReaderMessageSink(coreSession, methodHolder, true);
}
public void onStreamStart(Reader reader)
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
index 4e21e76d317..a927fd560f2 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
@@ -30,6 +30,7 @@ import org.eclipse.jetty.ee10.websocket.jakarta.common.decoders.RegisteredDecode
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -46,7 +47,7 @@ public class DecodedBinaryMessageSinkTest extends AbstractMessageSinkTest
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
- DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(session.getCoreSession(), copyHandle, decoders);
+ DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(session.getCoreSession(), MethodHolder.from(copyHandle), decoders);
FutureCallback finCallback = new FutureCallback();
ByteBuffer data = ByteBuffer.allocate(16);
@@ -69,7 +70,7 @@ public class DecodedBinaryMessageSinkTest extends AbstractMessageSinkTest
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
- DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(session.getCoreSession(), copyHandle, decoders);
+ DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(session.getCoreSession(), MethodHolder.from(copyHandle), decoders);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
index 19f2d82c00c..db830c3d2a1 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
@@ -33,6 +33,7 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -49,7 +50,7 @@ public class DecodedBinaryStreamMessageSinkTest extends AbstractMessageSinkTest
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
- DecodedBinaryStreamMessageSink sink = new DecodedBinaryStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
+ DecodedBinaryStreamMessageSink sink = new DecodedBinaryStreamMessageSink<>(session.getCoreSession(), MethodHolder.from(copyHandle), decoders);
FutureCallback finCallback = new FutureCallback();
ByteBuffer data = ByteBuffer.allocate(16);
@@ -72,7 +73,7 @@ public class DecodedBinaryStreamMessageSinkTest extends AbstractMessageSinkTest
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
- DecodedBinaryStreamMessageSink sink = new DecodedBinaryStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
+ DecodedBinaryStreamMessageSink sink = new DecodedBinaryStreamMessageSink<>(session.getCoreSession(), MethodHolder.from(copyHandle), decoders);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
index e3fccf35041..eac4ee36f05 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
@@ -31,6 +31,7 @@ import org.eclipse.jetty.ee10.websocket.jakarta.common.decoders.RegisteredDecode
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -47,7 +48,7 @@ public class DecodedTextMessageSinkTest extends AbstractMessageSinkTest
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
- DecodedTextMessageSink sink = new DecodedTextMessageSink<>(session.getCoreSession(), copyHandle, decoders);
+ DecodedTextMessageSink sink = new DecodedTextMessageSink<>(session.getCoreSession(), MethodHolder.from(copyHandle), decoders);
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.TEXT).setPayload("2018.02.13").setFin(true), finCallback);
@@ -65,7 +66,7 @@ public class DecodedTextMessageSinkTest extends AbstractMessageSinkTest
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
- DecodedTextMessageSink sink = new DecodedTextMessageSink<>(session.getCoreSession(), copyHandle, decoders);
+ DecodedTextMessageSink sink = new DecodedTextMessageSink<>(session.getCoreSession(), MethodHolder.from(copyHandle), decoders);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
index fe83857050c..9647c606886 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
@@ -34,6 +34,7 @@ import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -50,7 +51,7 @@ public class DecodedTextStreamMessageSinkTest extends AbstractMessageSinkTest
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
- DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
+ DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), MethodHolder.from(copyHandle), decoders);
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.TEXT).setPayload("2018.02.13").setFin(true), finCallback);
@@ -68,7 +69,7 @@ public class DecodedTextStreamMessageSinkTest extends AbstractMessageSinkTest
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
- DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
+ DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), MethodHolder.from(copyHandle), decoders);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
index b91f0e28702..3e08f41e03f 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
@@ -32,6 +32,7 @@ import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
import org.eclipse.jetty.websocket.core.messages.InputStreamMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -46,7 +47,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
+ InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), MethodHolder.from(copyHandle), true);
FutureCallback finCallback = new FutureCallback();
ByteBuffer data = BufferUtil.toBuffer("Hello World", UTF_8);
@@ -64,7 +65,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
+ InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), MethodHolder.from(copyHandle), true);
FutureCallback fin1Callback = new FutureCallback();
ByteBuffer data1 = BufferUtil.toBuffer("Hello World", UTF_8);
@@ -95,7 +96,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
+ InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), MethodHolder.from(copyHandle), true);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
@@ -120,7 +121,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
{
InputStreamCopy copy = new InputStreamCopy();
MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
- InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
+ InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), MethodHolder.from(copyHandle), true);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/ReaderMessageSinkTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
index af3264e8d91..5cc83ebc99c 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
@@ -28,6 +28,7 @@ import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
import org.eclipse.jetty.websocket.core.messages.ReaderMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -41,7 +42,7 @@ public class ReaderMessageSinkTest extends AbstractMessageSinkTest
CompletableFuture copyFuture = new CompletableFuture<>();
ReaderCopy copy = new ReaderCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Reader.class);
- ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle, true);
+ ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), MethodHolder.from(copyHandle), true);
FutureCallback finCallback = new FutureCallback();
sink.accept(new Frame(OpCode.TEXT).setPayload("Hello World"), finCallback);
@@ -58,7 +59,7 @@ public class ReaderMessageSinkTest extends AbstractMessageSinkTest
CompletableFuture copyFuture = new CompletableFuture<>();
ReaderCopy copy = new ReaderCopy(copyFuture);
MethodHandle copyHandle = getAcceptHandle(copy, Reader.class);
- ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle, true);
+ ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), MethodHolder.from(copyHandle), true);
FutureCallback callback1 = new FutureCallback();
FutureCallback callback2 = new FutureCallback();
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java
index 578a5ae83e6..6fd32c011a7 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java
@@ -23,6 +23,7 @@ import jakarta.websocket.Session;
import org.eclipse.jetty.ee10.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.eclipse.jetty.websocket.core.util.ReflectUtils;
import org.junit.jupiter.api.Test;
@@ -57,6 +58,12 @@ public class InvokerUtilsStaticParamsTest
private static MethodHandles.Lookup lookup = MethodHandles.lookup();
+ private MethodHolder getMethodHolder(Method method, String[] namedVariables, InvokerUtils.Arg... args)
+ {
+ MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables, args);
+ return MethodHolder.from(methodHandle);
+ }
+
@Test
public void testOnlyParamString() throws Throwable
{
@@ -70,21 +77,21 @@ public class InvokerUtilsStaticParamsTest
// Raw Calling Args - none specified
// Get basic method handle (without a instance to call against) - this is what the metadata stores
- MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables);
+ MethodHolder methodHolder = getMethodHolder(method, namedVariables);
// Some point later an actual instance is needed, which has static named parameters
Map templateValues = new HashMap<>();
templateValues.put("fruit", "pear");
// Bind the static values, in same order as declared
- methodHandle = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHandle, namedVariables, templateValues);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHolder, namedVariables, templateValues);
// Assign an instance to call.
Foo foo = new Foo();
- methodHandle = methodHandle.bindTo(foo);
+ methodHolder = methodHolder.bindTo(foo);
// Call method against instance
- String result = (String)methodHandle.invoke();
+ String result = (String)methodHolder.invoke();
assertThat("Result", result, is("onFruit('pear')"));
}
@@ -99,21 +106,21 @@ public class InvokerUtilsStaticParamsTest
};
// Get basic method handle (without a instance to call against) - this is what the metadata stores
- MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables);
+ MethodHolder methodHolder = getMethodHolder(method, namedVariables);
// Some point later an actual instance is needed, which has static named parameters
Map templateValues = new HashMap<>();
templateValues.put("count", "2222");
// Bind the static values for the variables, in same order as the variables were declared
- methodHandle = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHandle, namedVariables, templateValues);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHolder, namedVariables, templateValues);
// Assign an instance to call.
Foo foo = new Foo();
- methodHandle = methodHandle.bindTo(foo);
+ methodHolder = methodHolder.bindTo(foo);
// Call method against instance
- String result = (String)methodHandle.invoke();
+ String result = (String)methodHolder.invoke();
assertThat("Result", result, is("onCount(2222)"));
}
@@ -130,21 +137,21 @@ public class InvokerUtilsStaticParamsTest
final InvokerUtils.Arg ARG_LABEL = new InvokerUtils.Arg(String.class).required();
// Get basic method handle (without a instance to call against) - this is what the metadata stores
- MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables, ARG_LABEL);
+ MethodHolder methodHolder = getMethodHolder(method, namedVariables, ARG_LABEL);
// Some point later an actual instance is needed, which has static named parameters
Map templateValues = new HashMap<>();
templateValues.put("count", "444");
// Bind the static values for the variables, in same order as the variables were declared
- methodHandle = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHandle, namedVariables, templateValues);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHolder, namedVariables, templateValues);
// Assign an instance to call.
Foo foo = new Foo();
- methodHandle = methodHandle.bindTo(foo);
+ methodHolder = methodHolder.bindTo(foo);
// Call method against instance
- String result = (String)methodHandle.invoke("cherry");
+ String result = (String)methodHolder.invoke("cherry");
assertThat("Result", result, is("onLabeledCount('cherry', 444)"));
}
}
diff --git a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/coders/DecoderTextStreamTest.java b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/coders/DecoderTextStreamTest.java
index 73b8f3f3244..3e3f83780fb 100644
--- a/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/coders/DecoderTextStreamTest.java
+++ b/jetty-ee10/jetty-ee10-websocket/jetty-ee10-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee10/websocket/jakarta/tests/coders/DecoderTextStreamTest.java
@@ -33,6 +33,7 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -80,7 +81,7 @@ public class DecoderTextStreamTest extends AbstractClientSessionTest
});
List decoders = toRegisteredDecoderList(QuotesDecoder.class, Quotes.class);
- DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), quoteHandle, decoders);
+ DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), MethodHolder.from(quoteHandle), decoders);
List callbacks = new ArrayList<>();
FutureCallback finCallback = null;
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaMessagePartialMethodHolder.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaMessagePartialMethodHolder.java
new file mode 100644
index 00000000000..912b14989f7
--- /dev/null
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaMessagePartialMethodHolder.java
@@ -0,0 +1,59 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.ee11.websocket.jakarta.common;
+
+import java.lang.invoke.WrongMethodTypeException;
+
+import jakarta.websocket.MessageHandler;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
+
+class JakartaMessagePartialMethodHolder implements MethodHolder
+{
+ private final MessageHandler.Partial _messageHandler;
+
+ public JakartaMessagePartialMethodHolder(MessageHandler.Partial messageHandler)
+ {
+ _messageHandler = messageHandler;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object invoke(Object... args) throws Throwable
+ {
+ if (args.length != 2)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 2, args.length));
+ _messageHandler.onMessage((T)args[0], (boolean)args[1]);
+ return null;
+ }
+
+ @Override
+ public Class> parameterType(int idx)
+ {
+ switch (idx)
+ {
+ case 0:
+ return Object.class;
+ case 1:
+ return boolean.class;
+ default:
+ throw new IndexOutOfBoundsException(idx);
+ }
+ }
+
+ @Override
+ public Class> returnType()
+ {
+ return void.class;
+ }
+}
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaMessageWholeMethodHolder.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaMessageWholeMethodHolder.java
new file mode 100644
index 00000000000..1dc900f343a
--- /dev/null
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaMessageWholeMethodHolder.java
@@ -0,0 +1,57 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.ee11.websocket.jakarta.common;
+
+import java.lang.invoke.WrongMethodTypeException;
+
+import jakarta.websocket.MessageHandler;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
+
+class JakartaMessageWholeMethodHolder implements MethodHolder
+{
+ private final MessageHandler.Whole _messageHandler;
+
+ public JakartaMessageWholeMethodHolder(MessageHandler.Whole messageHandler)
+ {
+ _messageHandler = messageHandler;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object invoke(Object... args) throws Throwable
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ _messageHandler.onMessage((T)args[0]);
+ return null;
+ }
+
+ @Override
+ public Class> parameterType(int idx)
+ {
+ switch (idx)
+ {
+ case 0:
+ return Object.class;
+ default:
+ throw new IndexOutOfBoundsException(idx);
+ }
+ }
+
+ @Override
+ public Class> returnType()
+ {
+ return void.class;
+ }
+}
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketFrameHandler.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
index 5d868b33fbb..edb8777d31f 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
@@ -13,8 +13,6 @@
package org.eclipse.jetty.ee11.websocket.jakarta.common;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
@@ -51,6 +49,7 @@ import org.eclipse.jetty.websocket.core.messages.PartialByteArrayMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialStringMessageSink;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -62,10 +61,10 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
private final Object endpointInstance;
private final AtomicBoolean closeNotified = new AtomicBoolean();
- private MethodHandle openHandle;
- private MethodHandle closeHandle;
- private MethodHandle errorHandle;
- private MethodHandle pongHandle;
+ private MethodHolder openHandle;
+ private MethodHolder closeHandle;
+ private MethodHolder errorHandle;
+ private MethodHolder pongHandle;
private JakartaWebSocketMessageMetadata textMetadata;
private JakartaWebSocketMessageMetadata binaryMetadata;
private final UpgradeRequest upgradeRequest;
@@ -79,12 +78,12 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
protected byte dataType = OpCode.UNDEFINED;
public JakartaWebSocketFrameHandler(JakartaWebSocketContainer container,
- UpgradeRequest upgradeRequest,
+ UpgradeRequest upgradeRequest,
Object endpointInstance,
- MethodHandle openHandle, MethodHandle closeHandle, MethodHandle errorHandle,
- JakartaWebSocketMessageMetadata textMetadata,
- JakartaWebSocketMessageMetadata binaryMetadata,
- MethodHandle pongHandle,
+ MethodHolder openHandle, MethodHolder closeHandle, MethodHolder errorHandle,
+ JakartaWebSocketMessageMetadata textMetadata,
+ JakartaWebSocketMessageMetadata binaryMetadata,
+ MethodHolder pongHandle,
EndpointConfig endpointConfig)
{
this.logger = LoggerFactory.getLogger(endpointInstance.getClass());
@@ -147,10 +146,10 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
if (actualTextMetadata.isMaxMessageSizeSet())
session.setMaxTextMessageBufferSize(actualTextMetadata.getMaxMessageSize());
- MethodHandle methodHandle = actualTextMetadata.getMethodHandle();
- methodHandle = InvokerUtils.bindTo(methodHandle, endpointInstance, endpointConfig, session);
- methodHandle = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHandle, session);
- actualTextMetadata.setMethodHandle(methodHandle);
+ MethodHolder methodHolder = actualTextMetadata.getMethodHolder();
+ methodHolder = InvokerUtils.bindTo(methodHolder, endpointInstance, endpointConfig, session);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHolder, session);
+ actualTextMetadata.setMethodHolder(methodHolder);
textSink = JakartaWebSocketFrameHandlerFactory.createMessageSink(session, actualTextMetadata);
textMetadata = actualTextMetadata;
@@ -162,10 +161,10 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
if (actualBinaryMetadata.isMaxMessageSizeSet())
session.setMaxBinaryMessageBufferSize(actualBinaryMetadata.getMaxMessageSize());
- MethodHandle methodHandle = actualBinaryMetadata.getMethodHandle();
+ MethodHolder methodHandle = actualBinaryMetadata.getMethodHolder();
methodHandle = InvokerUtils.bindTo(methodHandle, endpointInstance, endpointConfig, session);
methodHandle = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHandle, session);
- actualBinaryMetadata.setMethodHandle(methodHandle);
+ actualBinaryMetadata.setMethodHolder(methodHandle);
binarySink = JakartaWebSocketFrameHandlerFactory.createMessageSink(session, actualBinaryMetadata);
binaryMetadata = actualBinaryMetadata;
@@ -346,116 +345,88 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
public void addMessageHandler(Class clazz, MessageHandler.Partial handler)
{
- try
+ JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
+ metadata.setMethodHolder(new JakartaMessagePartialMethodHolder<>(handler));
+ byte basicType;
+ // MessageHandler.Partial has no decoder support!
+ if (byte[].class.isAssignableFrom(clazz))
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(MessageHandler.Partial.class, "onMessage", MethodType.methodType(void.class, Object.class, boolean.class))
- .bindTo(handler);
+ basicType = OpCode.BINARY;
+ metadata.setSinkClass(PartialByteArrayMessageSink.class);
+ }
+ else if (ByteBuffer.class.isAssignableFrom(clazz))
+ {
+ basicType = OpCode.BINARY;
+ metadata.setSinkClass(PartialByteBufferMessageSink.class);
+ }
+ else if (String.class.isAssignableFrom(clazz))
+ {
+ basicType = OpCode.TEXT;
+ metadata.setSinkClass(PartialStringMessageSink.class);
+ }
+ else
+ {
+ throw new RuntimeException(
+ "Unable to add " + handler.getClass().getName() + " with type " + clazz + ": only supported types byte[], " + ByteBuffer.class.getName() +
+ ", " + String.class.getName());
+ }
- JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
- metadata.setMethodHandle(methodHandle);
- byte basicType;
- // MessageHandler.Partial has no decoder support!
- if (byte[].class.isAssignableFrom(clazz))
- {
- basicType = OpCode.BINARY;
- metadata.setSinkClass(PartialByteArrayMessageSink.class);
- }
- else if (ByteBuffer.class.isAssignableFrom(clazz))
- {
- basicType = OpCode.BINARY;
- metadata.setSinkClass(PartialByteBufferMessageSink.class);
- }
- else if (String.class.isAssignableFrom(clazz))
- {
- basicType = OpCode.TEXT;
- metadata.setSinkClass(PartialStringMessageSink.class);
- }
- else
- {
- throw new RuntimeException(
- "Unable to add " + handler.getClass().getName() + " with type " + clazz + ": only supported types byte[], " + ByteBuffer.class.getName() +
- ", " + String.class.getName());
- }
-
- // Register the Metadata as a MessageHandler.
- registerMessageHandler(clazz, handler, basicType, metadata);
- }
- catch (NoSuchMethodException e)
- {
- throw new IllegalStateException("Unable to find method", e);
- }
- catch (IllegalAccessException e)
- {
- throw new IllegalStateException("Unable to access " + handler.getClass().getName(), e);
- }
+ // Register the Metadata as a MessageHandler.
+ registerMessageHandler(clazz, handler, basicType, metadata);
}
public void addMessageHandler(Class clazz, MessageHandler.Whole handler)
{
- try
+ MethodHolder methodHolder = new JakartaMessageWholeMethodHolder<>(handler);
+
+ if (PongMessage.class.isAssignableFrom(clazz))
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(MessageHandler.Whole.class, "onMessage", MethodType.methodType(void.class, Object.class))
- .bindTo(handler);
-
- if (PongMessage.class.isAssignableFrom(clazz))
- {
- assertBasicTypeNotRegistered(OpCode.PONG, handler);
- this.pongHandle = methodHandle;
- registerMessageHandler(OpCode.PONG, clazz, handler, null);
- return;
- }
-
- AvailableDecoders availableDecoders = session.getDecoders();
- RegisteredDecoder registeredDecoder = availableDecoders.getFirstRegisteredDecoder(clazz);
- if (registeredDecoder == null)
- throw new IllegalStateException("Unable to find Decoder for type: " + clazz);
-
- // Create the message metadata specific to the MessageHandler type.
- JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
- metadata.setMethodHandle(methodHandle);
- byte basicType;
- if (registeredDecoder.implementsInterface(Decoder.Binary.class))
- {
- basicType = OpCode.BINARY;
- metadata.setRegisteredDecoders(availableDecoders.getBinaryDecoders(clazz));
- metadata.setSinkClass(DecodedBinaryMessageSink.class);
- }
- else if (registeredDecoder.implementsInterface(Decoder.BinaryStream.class))
- {
- basicType = OpCode.BINARY;
- metadata.setRegisteredDecoders(availableDecoders.getBinaryStreamDecoders(clazz));
- metadata.setSinkClass(DecodedBinaryStreamMessageSink.class);
- }
- else if (registeredDecoder.implementsInterface(Decoder.Text.class))
- {
- basicType = OpCode.TEXT;
- metadata.setRegisteredDecoders(availableDecoders.getTextDecoders(clazz));
- metadata.setSinkClass(DecodedTextMessageSink.class);
- }
- else if (registeredDecoder.implementsInterface(Decoder.TextStream.class))
- {
- basicType = OpCode.TEXT;
- metadata.setRegisteredDecoders(availableDecoders.getTextStreamDecoders(clazz));
- metadata.setSinkClass(DecodedTextStreamMessageSink.class);
- }
- else
- {
- throw new RuntimeException("Unable to add " + handler.getClass().getName() + ": type " + clazz + " is unrecognized by declared decoders");
- }
-
- // Register the Metadata as a MessageHandler.
- registerMessageHandler(clazz, handler, basicType, metadata);
+ assertBasicTypeNotRegistered(OpCode.PONG, handler);
+ this.pongHandle = methodHolder;
+ registerMessageHandler(OpCode.PONG, clazz, handler, null);
+ return;
}
- catch (NoSuchMethodException e)
+
+ AvailableDecoders availableDecoders = session.getDecoders();
+ RegisteredDecoder registeredDecoder = availableDecoders.getFirstRegisteredDecoder(clazz);
+ if (registeredDecoder == null)
+ throw new IllegalStateException("Unable to find Decoder for type: " + clazz);
+
+ // Create the message metadata specific to the MessageHandler type.
+ JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
+ metadata.setMethodHolder(methodHolder);
+ byte basicType;
+ if (registeredDecoder.implementsInterface(Decoder.Binary.class))
{
- throw new IllegalStateException("Unable to find method", e);
+ basicType = OpCode.BINARY;
+ metadata.setRegisteredDecoders(availableDecoders.getBinaryDecoders(clazz));
+ metadata.setSinkClass(DecodedBinaryMessageSink.class);
}
- catch (IllegalAccessException e)
+ else if (registeredDecoder.implementsInterface(Decoder.BinaryStream.class))
{
- throw new IllegalStateException("Unable to access " + handler.getClass().getName(), e);
+ basicType = OpCode.BINARY;
+ metadata.setRegisteredDecoders(availableDecoders.getBinaryStreamDecoders(clazz));
+ metadata.setSinkClass(DecodedBinaryStreamMessageSink.class);
}
+ else if (registeredDecoder.implementsInterface(Decoder.Text.class))
+ {
+ basicType = OpCode.TEXT;
+ metadata.setRegisteredDecoders(availableDecoders.getTextDecoders(clazz));
+ metadata.setSinkClass(DecodedTextMessageSink.class);
+ }
+ else if (registeredDecoder.implementsInterface(Decoder.TextStream.class))
+ {
+ basicType = OpCode.TEXT;
+ metadata.setRegisteredDecoders(availableDecoders.getTextStreamDecoders(clazz));
+ metadata.setSinkClass(DecodedTextStreamMessageSink.class);
+ }
+ else
+ {
+ throw new RuntimeException("Unable to add " + handler.getClass().getName() + ": type " + clazz + " is unrecognized by declared decoders");
+ }
+
+ // Register the Metadata as a MessageHandler.
+ registerMessageHandler(clazz, handler, basicType, metadata);
}
private void assertBasicTypeNotRegistered(byte basicWebSocketType, MessageHandler replacement)
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
index 95ca9ea7fa8..966fff0ba37 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
@@ -52,6 +52,7 @@ import org.eclipse.jetty.websocket.core.messages.PartialByteArrayMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialStringMessageSink;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.eclipse.jetty.websocket.core.util.ReflectUtils;
public abstract class JakartaWebSocketFrameHandlerFactory
@@ -135,10 +136,10 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (metadata == null)
return null;
- MethodHandle openHandle = metadata.getOpenHandle();
- MethodHandle closeHandle = metadata.getCloseHandle();
- MethodHandle errorHandle = metadata.getErrorHandle();
- MethodHandle pongHandle = metadata.getPongHandle();
+ MethodHolder openHandle = MethodHolder.from(metadata.getOpenHandle());
+ MethodHolder closeHandle = MethodHolder.from(metadata.getCloseHandle());
+ MethodHolder errorHandle = MethodHolder.from(metadata.getErrorHandle());
+ MethodHolder pongHandle = MethodHolder.from(metadata.getPongHandle());
JakartaWebSocketMessageMetadata textMetadata = JakartaWebSocketMessageMetadata.copyOf(metadata.getTextMetadata());
JakartaWebSocketMessageMetadata binaryMetadata = JakartaWebSocketMessageMetadata.copyOf(metadata.getBinaryMetadata());
@@ -156,9 +157,9 @@ public abstract class JakartaWebSocketFrameHandlerFactory
pongHandle = bindTemplateVariables(pongHandle, namedVariables, pathParams);
if (textMetadata != null)
- textMetadata.setMethodHandle(bindTemplateVariables(textMetadata.getMethodHandle(), namedVariables, pathParams));
+ textMetadata.setMethodHolder(bindTemplateVariables(textMetadata.getMethodHolder(), namedVariables, pathParams));
if (binaryMetadata != null)
- binaryMetadata.setMethodHandle(bindTemplateVariables(binaryMetadata.getMethodHandle(), namedVariables, pathParams));
+ binaryMetadata.setMethodHolder(bindTemplateVariables(binaryMetadata.getMethodHolder(), namedVariables, pathParams));
}
openHandle = InvokerUtils.bindTo(openHandle, endpoint);
@@ -190,15 +191,15 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (AbstractDecodedMessageSink.class.isAssignableFrom(msgMetadata.getSinkClass()))
{
MethodHandle ctorHandle = lookup.findConstructor(msgMetadata.getSinkClass(),
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, List.class));
+ MethodType.methodType(void.class, CoreSession.class, MethodHolder.class, List.class));
List registeredDecoders = msgMetadata.getRegisteredDecoders();
- return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHandle(), registeredDecoders);
+ return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHolder(), registeredDecoders);
}
else
{
MethodHandle ctorHandle = lookup.findConstructor(msgMetadata.getSinkClass(),
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, boolean.class));
- return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHandle(), true);
+ MethodType.methodType(void.class, CoreSession.class, MethodHolder.class, boolean.class));
+ return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHolder(), true);
}
}
catch (NoSuchMethodException e)
@@ -219,23 +220,19 @@ public abstract class JakartaWebSocketFrameHandlerFactory
}
}
- public static MethodHandle wrapNonVoidReturnType(MethodHandle handle, JakartaWebSocketSession session)
+ public static MethodHolder wrapNonVoidReturnType(MethodHolder holder, JakartaWebSocketSession session)
{
- if (handle == null)
+ if (holder == null)
return null;
- if (handle.type().returnType() == Void.TYPE)
- return handle;
+ if (holder.returnType() == Void.TYPE)
+ return holder;
- // Technique from https://stackoverflow.com/questions/48505787/methodhandle-with-general-non-void-return-filter
-
- // Change the return type of the to be Object so it will match exact with JakartaWebSocketSession.filterReturnType(Object)
- handle = handle.asType(handle.type().changeReturnType(Object.class));
-
- // Filter the method return type to a call to JakartaWebSocketSession.filterReturnType() bound to this session
- handle = MethodHandles.filterReturnValue(handle, FILTER_RETURN_TYPE_METHOD.bindTo(session));
-
- return handle;
+ return args ->
+ {
+ session.filterReturnType(holder.invoke(args));
+ return null;
+ };
}
private MethodHandle toMethodHandle(MethodHandles.Lookup lookup, Method method)
@@ -360,7 +357,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (methodHandle != null)
{
msgMetadata.setSinkClass(PartialStringMessageSink.class);
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
metadata.setTextMetadata(msgMetadata, onMsg);
return true;
}
@@ -370,7 +367,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (methodHandle != null)
{
msgMetadata.setSinkClass(PartialByteBufferMessageSink.class);
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
metadata.setBinaryMetadata(msgMetadata, onMsg);
return true;
}
@@ -380,7 +377,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (methodHandle != null)
{
msgMetadata.setSinkClass(PartialByteArrayMessageSink.class);
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
metadata.setBinaryMetadata(msgMetadata, onMsg);
return true;
}
@@ -423,7 +420,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
objectType = decoder.objectType;
}
MethodHandle methodHandle = getMethodHandle.apply(getArgsFor(objectType));
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
// Set the sinkClass and then set the MessageMetadata on the FrameHandlerMetadata
if (interfaceType.equals(Decoder.Text.class))
@@ -508,7 +505,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
* have been statically assigned a converted value (and removed from the resulting {@link MethodHandle#type()}, or null if
* no {@code target} MethodHandle was provided.
*/
- public static MethodHandle bindTemplateVariables(MethodHandle target, String[] namedVariables, Map templateValues)
+ public static MethodHolder bindTemplateVariables(MethodHolder target, String[] namedVariables, Map templateValues)
{
if (target == null)
{
@@ -517,7 +514,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
final int IDX = 1;
- MethodHandle retHandle = target;
+ MethodHolder retHandle = target;
if ((templateValues == null) || (templateValues.isEmpty()))
{
@@ -527,54 +524,58 @@ public abstract class JakartaWebSocketFrameHandlerFactory
for (String variableName : namedVariables)
{
String strValue = templateValues.get(variableName);
- Class> type = retHandle.type().parameterType(IDX);
+ Class> type = retHandle.parameterType(IDX);
try
{
if (String.class.isAssignableFrom(type))
{
- retHandle = MethodHandles.insertArguments(retHandle, IDX, strValue);
+ retHandle = retHandle.bindTo(strValue, IDX);
}
else if (Integer.class.isAssignableFrom(type) || Integer.TYPE.isAssignableFrom(type))
{
Integer intValue = Integer.parseInt(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, intValue);
+ retHandle = retHandle.bindTo(intValue, IDX);
}
else if (Long.class.isAssignableFrom(type) || Long.TYPE.isAssignableFrom(type))
{
Long longValue = Long.parseLong(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, longValue);
+ retHandle = retHandle.bindTo(longValue, IDX);
}
else if (Short.class.isAssignableFrom(type) || Short.TYPE.isAssignableFrom(type))
{
Short shortValue = Short.parseShort(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, shortValue);
+ retHandle = retHandle.bindTo(shortValue, IDX);
+
}
else if (Float.class.isAssignableFrom(type) || Float.TYPE.isAssignableFrom(type))
{
Float floatValue = Float.parseFloat(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, floatValue);
+ retHandle = retHandle.bindTo(floatValue, IDX);
+
}
else if (Double.class.isAssignableFrom(type) || Double.TYPE.isAssignableFrom(type))
{
Double doubleValue = Double.parseDouble(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, doubleValue);
+ retHandle = retHandle.bindTo(doubleValue, IDX);
+
}
else if (Boolean.class.isAssignableFrom(type) || Boolean.TYPE.isAssignableFrom(type))
{
Boolean boolValue = Boolean.parseBoolean(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, boolValue);
+ retHandle = retHandle.bindTo(boolValue, IDX);
+
}
else if (Character.class.isAssignableFrom(type) || Character.TYPE.isAssignableFrom(type))
{
if (strValue.length() != 1)
throw new IllegalArgumentException("Invalid Size");
Character charValue = strValue.charAt(0);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, charValue);
+ retHandle = retHandle.bindTo(charValue, IDX);
}
else if (Byte.class.isAssignableFrom(type) || Byte.TYPE.isAssignableFrom(type))
{
Byte b = Byte.parseByte(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, b);
+ retHandle = retHandle.bindTo(b, IDX);
}
else
{
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java
index 80876d0e3a1..f26a7e82a92 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java
@@ -13,15 +13,15 @@
package org.eclipse.jetty.ee11.websocket.jakarta.common;
-import java.lang.invoke.MethodHandle;
import java.util.List;
import org.eclipse.jetty.ee11.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class JakartaWebSocketMessageMetadata
{
- private MethodHandle methodHandle;
+ private MethodHolder methodHolder;
private Class extends MessageSink> sinkClass;
private List registeredDecoders;
@@ -34,7 +34,7 @@ public class JakartaWebSocketMessageMetadata
return null;
JakartaWebSocketMessageMetadata copy = new JakartaWebSocketMessageMetadata();
- copy.methodHandle = metadata.methodHandle;
+ copy.methodHolder = metadata.methodHolder;
copy.sinkClass = metadata.sinkClass;
copy.registeredDecoders = metadata.registeredDecoders;
copy.maxMessageSize = metadata.maxMessageSize;
@@ -58,14 +58,14 @@ public class JakartaWebSocketMessageMetadata
this.maxMessageSizeSet = true;
}
- public MethodHandle getMethodHandle()
+ public MethodHolder getMethodHolder()
{
- return methodHandle;
+ return methodHolder;
}
- public void setMethodHandle(MethodHandle methodHandle)
+ public void setMethodHolder(MethodHolder methodHolder)
{
- this.methodHandle = methodHandle;
+ this.methodHolder = methodHolder;
}
public Class extends MessageSink> getSinkClass()
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java
index 575d0489a7a..b30fdab99ac 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java
@@ -13,7 +13,6 @@
package org.eclipse.jetty.ee11.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
import java.util.List;
import java.util.stream.Collectors;
@@ -25,6 +24,7 @@ import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,12 +32,12 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
private static final Logger LOG = LoggerFactory.getLogger(AbstractDecodedMessageSink.class);
- private final MethodHandle _methodHandle;
+ private final MethodHolder _methodHolder;
private final MessageSink _messageSink;
- public AbstractDecodedMessageSink(CoreSession coreSession, MethodHandle methodHandle)
+ public AbstractDecodedMessageSink(CoreSession coreSession, MethodHolder methodHolder)
{
- _methodHandle = methodHandle;
+ _methodHolder = methodHolder;
try
{
@@ -58,7 +58,7 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
try
{
- _methodHandle.invoke(message);
+ _methodHolder.invoke(message);
}
catch (Throwable t)
{
@@ -67,7 +67,7 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
}
/**
- * @return a message sink which will first decode the message then pass it to {@link #_methodHandle}.
+ * @return a message sink which will first decode the message then pass it to {@link #_methodHolder}.
* @throws Exception for any error in creating the message sink.
*/
abstract MessageSink newMessageSink(CoreSession coreSession) throws Exception;
@@ -90,9 +90,9 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
protected final List _decoders;
- public Basic(CoreSession coreSession, MethodHandle methodHandle, List decoders)
+ public Basic(CoreSession coreSession, MethodHolder methodHolder, List decoders)
{
- super(coreSession, methodHandle);
+ super(coreSession, methodHolder);
if (decoders.isEmpty())
throw new IllegalArgumentException("Require at least one decoder for " + this.getClass());
_decoders = decoders.stream()
@@ -105,9 +105,9 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
protected final T _decoder;
- public Stream(CoreSession coreSession, MethodHandle methodHandle, List decoders)
+ public Stream(CoreSession coreSession, MethodHolder methodHolder, List decoders)
{
- super(coreSession, methodHandle);
+ super(coreSession, methodHolder);
if (decoders.size() != 1)
throw new IllegalArgumentException("Require exactly one decoder for " + this.getClass());
_decoder = decoders.get(0).getInstance();
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
index c280e40979e..b9f5fa0dbd2 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
@@ -13,20 +13,19 @@
package org.eclipse.jetty.ee11.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.nio.ByteBuffer;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee11.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee11.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.ByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,18 +33,23 @@ public class DecodedBinaryMessageSink extends AbstractDecodedMessageSink.Basi
{
private static final Logger LOG = LoggerFactory.getLogger(DecodedBinaryMessageSink.class);
- public DecodedBinaryMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedBinaryMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
- MessageSink newMessageSink(CoreSession coreSession) throws Exception
+ MessageSink newMessageSink(CoreSession coreSession)
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(DecodedBinaryMessageSink.class, "onWholeMessage", MethodType.methodType(void.class, ByteBuffer.class))
- .bindTo(this);
- return new ByteBufferMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onWholeMessage((ByteBuffer)args[0]);
+ return null;
+ };
+
+ return new ByteBufferMessageSink(coreSession, methodHolder, true);
}
public void onWholeMessage(ByteBuffer wholeMessage)
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
index 97e95c39b29..c3442e3b52d 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
@@ -15,34 +15,38 @@ package org.eclipse.jetty.ee11.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee11.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee11.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.InputStreamMessageSink;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class DecodedBinaryStreamMessageSink extends AbstractDecodedMessageSink.Stream>
{
- public DecodedBinaryStreamMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedBinaryStreamMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
- MessageSink newMessageSink(CoreSession coreSession) throws Exception
+ MessageSink newMessageSink(CoreSession coreSession)
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(DecodedBinaryStreamMessageSink.class, "onStreamStart", MethodType.methodType(void.class, InputStream.class))
- .bindTo(this);
- return new InputStreamMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onStreamStart((InputStream)args[0]);
+ return null;
+ };
+
+ return new InputStreamMessageSink(coreSession, methodHolder, true);
}
public void onStreamStart(InputStream stream)
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextMessageSink.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextMessageSink.java
index ccb18c696b1..53ad922af79 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextMessageSink.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextMessageSink.java
@@ -13,19 +13,18 @@
package org.eclipse.jetty.ee11.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee11.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee11.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
import org.eclipse.jetty.websocket.core.messages.StringMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,18 +32,23 @@ public class DecodedTextMessageSink extends AbstractDecodedMessageSink.Basic<
{
private static final Logger LOG = LoggerFactory.getLogger(DecodedTextMessageSink.class);
- public DecodedTextMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedTextMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
- MessageSink newMessageSink(CoreSession coreSession) throws NoSuchMethodException, IllegalAccessException
+ MessageSink newMessageSink(CoreSession coreSession)
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(getClass(), "onMessage", MethodType.methodType(void.class, String.class))
- .bindTo(this);
- return new StringMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onMessage((String)args[0]);
+ return null;
+ };
+
+ return new StringMessageSink(coreSession, methodHolder, true);
}
public void onMessage(String wholeMessage)
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
index 4872af80aea..04d64065f74 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
@@ -15,34 +15,38 @@ package org.eclipse.jetty.ee11.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.Reader;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee11.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee11.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
import org.eclipse.jetty.websocket.core.messages.ReaderMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class DecodedTextStreamMessageSink extends AbstractDecodedMessageSink.Stream>
{
- public DecodedTextStreamMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedTextStreamMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
MessageSink newMessageSink(CoreSession coreSession) throws Exception
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(DecodedTextStreamMessageSink.class, "onStreamStart", MethodType.methodType(void.class, Reader.class))
- .bindTo(this);
- return new ReaderMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onStreamStart((Reader)args[0]);
+ return null;
+ };
+
+ return new ReaderMessageSink(coreSession, methodHolder, true);
}
public void onStreamStart(Reader reader)
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/AbstractMessageSinkTest.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/AbstractMessageSinkTest.java
index 30978d02820..48228de9072 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/AbstractMessageSinkTest.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/AbstractMessageSinkTest.java
@@ -23,6 +23,7 @@ import jakarta.websocket.Decoder;
import org.eclipse.jetty.ee11.websocket.jakarta.common.AbstractSessionTest;
import org.eclipse.jetty.ee11.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee11.websocket.jakarta.common.decoders.RegisteredDecoder;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public abstract class AbstractMessageSinkTest extends AbstractSessionTest
{
@@ -43,7 +44,7 @@ public abstract class AbstractMessageSinkTest extends AbstractSessionTest
return List.of(new RegisteredDecoder(clazz, interfaceType, objectType, ClientEndpointConfig.Builder.create().build(), components));
}
- public MethodHandle getAcceptHandle(Consumer copy, Class type)
+ public MethodHolder getAcceptHandle(Consumer copy, Class type)
{
try
{
@@ -51,7 +52,7 @@ public abstract class AbstractMessageSinkTest extends AbstractSessionTest
String name = "accept";
MethodType methodType = MethodType.methodType(void.class, type);
MethodHandle handle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup().findVirtual(refc, name, methodType);
- return handle.bindTo(copy);
+ return MethodHolder.from(handle.bindTo(copy));
}
catch (NoSuchMethodException | IllegalAccessException e)
{
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
index 48c1eb34fff..f7801e8a3f6 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
@@ -13,7 +13,6 @@
package org.eclipse.jetty.ee11.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -30,6 +29,7 @@ import org.eclipse.jetty.ee11.websocket.jakarta.common.decoders.RegisteredDecode
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -44,7 +44,7 @@ public class DecodedBinaryMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(session.getCoreSession(), copyHandle, decoders);
@@ -67,7 +67,7 @@ public class DecodedBinaryMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(session.getCoreSession(), copyHandle, decoders);
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
index 4daf2e54372..51b39559bc4 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
@@ -15,7 +15,6 @@ package org.eclipse.jetty.ee11.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.invoke.MethodHandle;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -33,6 +32,7 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -47,7 +47,7 @@ public class DecodedBinaryStreamMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedBinaryStreamMessageSink sink = new DecodedBinaryStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
@@ -70,7 +70,7 @@ public class DecodedBinaryStreamMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedBinaryStreamMessageSink sink = new DecodedBinaryStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
index 556bc498b37..ea5bb08be2b 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
@@ -13,7 +13,6 @@
package org.eclipse.jetty.ee11.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -31,6 +30,7 @@ import org.eclipse.jetty.ee11.websocket.jakarta.common.decoders.RegisteredDecode
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -45,7 +45,7 @@ public class DecodedTextMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedTextMessageSink sink = new DecodedTextMessageSink<>(session.getCoreSession(), copyHandle, decoders);
@@ -63,7 +63,7 @@ public class DecodedTextMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedTextMessageSink sink = new DecodedTextMessageSink<>(session.getCoreSession(), copyHandle, decoders);
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
index 916e1cb7651..30907de3d47 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
@@ -15,7 +15,6 @@ package org.eclipse.jetty.ee11.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.Reader;
-import java.lang.invoke.MethodHandle;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -34,6 +33,7 @@ import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -48,7 +48,7 @@ public class DecodedTextStreamMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
@@ -66,7 +66,7 @@ public class DecodedTextStreamMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
index 9614ef299d2..8c55c90c329 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
@@ -16,7 +16,6 @@ package org.eclipse.jetty.ee11.websocket.jakarta.common.messages;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.invoke.MethodHandle;
import java.nio.ByteBuffer;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
@@ -32,6 +31,7 @@ import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
import org.eclipse.jetty.websocket.core.messages.InputStreamMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -45,7 +45,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
public void testInputStream1Message1Frame() throws InterruptedException, ExecutionException, TimeoutException
{
InputStreamCopy copy = new InputStreamCopy();
- MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, InputStream.class);
InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback finCallback = new FutureCallback();
@@ -63,7 +63,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
public void testInputStream2Messages2Frames() throws InterruptedException, ExecutionException, TimeoutException
{
InputStreamCopy copy = new InputStreamCopy();
- MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, InputStream.class);
InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback fin1Callback = new FutureCallback();
@@ -94,7 +94,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
public void testInputStream1Message3Frames() throws InterruptedException, ExecutionException, TimeoutException
{
InputStreamCopy copy = new InputStreamCopy();
- MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, InputStream.class);
InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
@@ -119,7 +119,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
public void testInputStream1Message4FramesEmptyFin() throws InterruptedException, ExecutionException, TimeoutException
{
InputStreamCopy copy = new InputStreamCopy();
- MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, InputStream.class);
InputStreamMessageSink sink = new InputStreamMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/ReaderMessageSinkTest.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
index 44918fcd332..b33a4f12ab8 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
@@ -16,7 +16,6 @@ package org.eclipse.jetty.ee11.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
-import java.lang.invoke.MethodHandle;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@@ -28,6 +27,7 @@ import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
import org.eclipse.jetty.websocket.core.messages.ReaderMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -40,7 +40,7 @@ public class ReaderMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
ReaderCopy copy = new ReaderCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Reader.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Reader.class);
ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback finCallback = new FutureCallback();
@@ -57,7 +57,7 @@ public class ReaderMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
ReaderCopy copy = new ReaderCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Reader.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Reader.class);
ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java
index d5970fa59db..daa86511342 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java
@@ -23,6 +23,7 @@ import jakarta.websocket.Session;
import org.eclipse.jetty.ee11.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.eclipse.jetty.websocket.core.util.ReflectUtils;
import org.junit.jupiter.api.Test;
@@ -57,6 +58,12 @@ public class InvokerUtilsStaticParamsTest
private static MethodHandles.Lookup lookup = MethodHandles.lookup();
+ private MethodHolder getMethodHolder(Method method, String[] namedVariables, InvokerUtils.Arg... args)
+ {
+ MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables, args);
+ return MethodHolder.from(methodHandle);
+ }
+
@Test
public void testOnlyParamString() throws Throwable
{
@@ -70,21 +77,20 @@ public class InvokerUtilsStaticParamsTest
// Raw Calling Args - none specified
// Get basic method handle (without a instance to call against) - this is what the metadata stores
- MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables);
+ MethodHolder methodHolder = getMethodHolder(method, namedVariables);
// Some point later an actual instance is needed, which has static named parameters
Map templateValues = new HashMap<>();
templateValues.put("fruit", "pear");
// Bind the static values, in same order as declared
- methodHandle = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHandle, namedVariables, templateValues);
-
+ methodHolder = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHolder, namedVariables, templateValues);
// Assign an instance to call.
Foo foo = new Foo();
- methodHandle = methodHandle.bindTo(foo);
+ methodHolder = methodHolder.bindTo(foo);
// Call method against instance
- String result = (String)methodHandle.invoke();
+ String result = (String)methodHolder.invoke();
assertThat("Result", result, is("onFruit('pear')"));
}
@@ -99,21 +105,21 @@ public class InvokerUtilsStaticParamsTest
};
// Get basic method handle (without a instance to call against) - this is what the metadata stores
- MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables);
+ MethodHolder methodHolder = getMethodHolder(method, namedVariables);
// Some point later an actual instance is needed, which has static named parameters
Map templateValues = new HashMap<>();
templateValues.put("count", "2222");
// Bind the static values for the variables, in same order as the variables were declared
- methodHandle = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHandle, namedVariables, templateValues);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHolder, namedVariables, templateValues);
// Assign an instance to call.
Foo foo = new Foo();
- methodHandle = methodHandle.bindTo(foo);
+ methodHolder = methodHolder.bindTo(foo);
// Call method against instance
- String result = (String)methodHandle.invoke();
+ String result = (String)methodHolder.invoke();
assertThat("Result", result, is("onCount(2222)"));
}
@@ -130,21 +136,21 @@ public class InvokerUtilsStaticParamsTest
final InvokerUtils.Arg ARG_LABEL = new InvokerUtils.Arg(String.class).required();
// Get basic method handle (without a instance to call against) - this is what the metadata stores
- MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables, ARG_LABEL);
+ MethodHolder methodHolder = getMethodHolder(method, namedVariables, ARG_LABEL);
// Some point later an actual instance is needed, which has static named parameters
Map templateValues = new HashMap<>();
templateValues.put("count", "444");
// Bind the static values for the variables, in same order as the variables were declared
- methodHandle = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHandle, namedVariables, templateValues);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHolder, namedVariables, templateValues);
// Assign an instance to call.
Foo foo = new Foo();
- methodHandle = methodHandle.bindTo(foo);
+ methodHolder = methodHolder.bindTo(foo);
// Call method against instance
- String result = (String)methodHandle.invoke("cherry");
+ String result = (String)methodHolder.invoke("cherry");
assertThat("Result", result, is("onLabeledCount('cherry', 444)"));
}
}
diff --git a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/tests/coders/DecoderTextStreamTest.java b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/tests/coders/DecoderTextStreamTest.java
index 3e47efb211d..8c7d9cffa06 100644
--- a/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/tests/coders/DecoderTextStreamTest.java
+++ b/jetty-ee11/jetty-ee11-websocket/jetty-ee11-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee11/websocket/jakarta/tests/coders/DecoderTextStreamTest.java
@@ -33,6 +33,7 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -80,7 +81,7 @@ public class DecoderTextStreamTest extends AbstractClientSessionTest
});
List decoders = toRegisteredDecoderList(QuotesDecoder.class, Quotes.class);
- DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), quoteHandle, decoders);
+ DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), MethodHolder.from(quoteHandle), decoders);
List callbacks = new ArrayList<>();
FutureCallback finCallback = null;
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaMessagePartialMethodHolder.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaMessagePartialMethodHolder.java
new file mode 100644
index 00000000000..76ecd0effa9
--- /dev/null
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaMessagePartialMethodHolder.java
@@ -0,0 +1,59 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.ee9.websocket.jakarta.common;
+
+import java.lang.invoke.WrongMethodTypeException;
+
+import jakarta.websocket.MessageHandler;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
+
+class JakartaMessagePartialMethodHolder implements MethodHolder
+{
+ private final MessageHandler.Partial _messageHandler;
+
+ public JakartaMessagePartialMethodHolder(MessageHandler.Partial messageHandler)
+ {
+ _messageHandler = messageHandler;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object invoke(Object... args) throws Throwable
+ {
+ if (args.length != 2)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 2, args.length));
+ _messageHandler.onMessage((T)args[0], (boolean)args[1]);
+ return null;
+ }
+
+ @Override
+ public Class> parameterType(int idx)
+ {
+ switch (idx)
+ {
+ case 0:
+ return Object.class;
+ case 1:
+ return boolean.class;
+ default:
+ throw new IndexOutOfBoundsException(idx);
+ }
+ }
+
+ @Override
+ public Class> returnType()
+ {
+ return void.class;
+ }
+}
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaMessageWholeMethodHolder.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaMessageWholeMethodHolder.java
new file mode 100644
index 00000000000..73c0ce3ca13
--- /dev/null
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaMessageWholeMethodHolder.java
@@ -0,0 +1,57 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.ee9.websocket.jakarta.common;
+
+import java.lang.invoke.WrongMethodTypeException;
+
+import jakarta.websocket.MessageHandler;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
+
+class JakartaMessageWholeMethodHolder implements MethodHolder
+{
+ private final MessageHandler.Whole _messageHandler;
+
+ public JakartaMessageWholeMethodHolder(MessageHandler.Whole messageHandler)
+ {
+ _messageHandler = messageHandler;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object invoke(Object... args) throws Throwable
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ _messageHandler.onMessage((T)args[0]);
+ return null;
+ }
+
+ @Override
+ public Class> parameterType(int idx)
+ {
+ switch (idx)
+ {
+ case 0:
+ return Object.class;
+ default:
+ throw new IndexOutOfBoundsException(idx);
+ }
+ }
+
+ @Override
+ public Class> returnType()
+ {
+ return void.class;
+ }
+}
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandler.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
index 77fbcabffb6..edcc4aa61fc 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandler.java
@@ -13,8 +13,6 @@
package org.eclipse.jetty.ee9.websocket.jakarta.common;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
@@ -52,6 +50,7 @@ import org.eclipse.jetty.websocket.core.messages.PartialByteArrayMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialStringMessageSink;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -63,10 +62,10 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
private final Object endpointInstance;
private final AtomicBoolean closeNotified = new AtomicBoolean();
- private MethodHandle openHandle;
- private MethodHandle closeHandle;
- private MethodHandle errorHandle;
- private MethodHandle pongHandle;
+ private MethodHolder openHandle;
+ private MethodHolder closeHandle;
+ private MethodHolder errorHandle;
+ private MethodHolder pongHandle;
private JakartaWebSocketMessageMetadata textMetadata;
private JakartaWebSocketMessageMetadata binaryMetadata;
private final UpgradeRequest upgradeRequest;
@@ -81,12 +80,12 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
public JakartaWebSocketFrameHandler(JakartaWebSocketContainer container,
UpgradeRequest upgradeRequest,
- Object endpointInstance,
- MethodHandle openHandle, MethodHandle closeHandle, MethodHandle errorHandle,
+ Object endpointInstance,
+ MethodHolder openHandle, MethodHolder closeHandle, MethodHolder errorHandle,
JakartaWebSocketMessageMetadata textMetadata,
JakartaWebSocketMessageMetadata binaryMetadata,
- MethodHandle pongHandle,
- EndpointConfig endpointConfig)
+ MethodHolder pongHandle,
+ EndpointConfig endpointConfig)
{
this.logger = LoggerFactory.getLogger(endpointInstance.getClass());
@@ -148,10 +147,10 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
if (actualTextMetadata.isMaxMessageSizeSet())
session.setMaxTextMessageBufferSize(actualTextMetadata.getMaxMessageSize());
- MethodHandle methodHandle = actualTextMetadata.getMethodHandle();
- methodHandle = InvokerUtils.bindTo(methodHandle, endpointInstance, endpointConfig, session);
- methodHandle = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHandle, session);
- actualTextMetadata.setMethodHandle(methodHandle);
+ MethodHolder methodHolder = actualTextMetadata.getMethodHolder();
+ methodHolder = InvokerUtils.bindTo(methodHolder, endpointInstance, endpointConfig, session);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHolder, session);
+ actualTextMetadata.setMethodHolder(methodHolder);
textSink = JakartaWebSocketFrameHandlerFactory.createMessageSink(session, actualTextMetadata);
textMetadata = actualTextMetadata;
@@ -163,10 +162,10 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
if (actualBinaryMetadata.isMaxMessageSizeSet())
session.setMaxBinaryMessageBufferSize(actualBinaryMetadata.getMaxMessageSize());
- MethodHandle methodHandle = actualBinaryMetadata.getMethodHandle();
- methodHandle = InvokerUtils.bindTo(methodHandle, endpointInstance, endpointConfig, session);
- methodHandle = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHandle, session);
- actualBinaryMetadata.setMethodHandle(methodHandle);
+ MethodHolder methodHolder = actualBinaryMetadata.getMethodHolder();
+ methodHolder = InvokerUtils.bindTo(methodHolder, endpointInstance, endpointConfig, session);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHolder, session);
+ actualBinaryMetadata.setMethodHolder(methodHolder);
binarySink = JakartaWebSocketFrameHandlerFactory.createMessageSink(session, actualBinaryMetadata);
binaryMetadata = actualBinaryMetadata;
@@ -353,116 +352,88 @@ public class JakartaWebSocketFrameHandler implements FrameHandler
public void addMessageHandler(Class clazz, MessageHandler.Partial handler)
{
- try
+ JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
+ metadata.setMethodHolder(new JakartaMessagePartialMethodHolder<>(handler));
+ byte basicType;
+ // MessageHandler.Partial has no decoder support!
+ if (byte[].class.isAssignableFrom(clazz))
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(MessageHandler.Partial.class, "onMessage", MethodType.methodType(void.class, Object.class, boolean.class))
- .bindTo(handler);
+ basicType = OpCode.BINARY;
+ metadata.setSinkClass(PartialByteArrayMessageSink.class);
+ }
+ else if (ByteBuffer.class.isAssignableFrom(clazz))
+ {
+ basicType = OpCode.BINARY;
+ metadata.setSinkClass(PartialByteBufferMessageSink.class);
+ }
+ else if (String.class.isAssignableFrom(clazz))
+ {
+ basicType = OpCode.TEXT;
+ metadata.setSinkClass(PartialStringMessageSink.class);
+ }
+ else
+ {
+ throw new RuntimeException(
+ "Unable to add " + handler.getClass().getName() + " with type " + clazz + ": only supported types byte[], " + ByteBuffer.class.getName() +
+ ", " + String.class.getName());
+ }
- JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
- metadata.setMethodHandle(methodHandle);
- byte basicType;
- // MessageHandler.Partial has no decoder support!
- if (byte[].class.isAssignableFrom(clazz))
- {
- basicType = OpCode.BINARY;
- metadata.setSinkClass(PartialByteArrayMessageSink.class);
- }
- else if (ByteBuffer.class.isAssignableFrom(clazz))
- {
- basicType = OpCode.BINARY;
- metadata.setSinkClass(PartialByteBufferMessageSink.class);
- }
- else if (String.class.isAssignableFrom(clazz))
- {
- basicType = OpCode.TEXT;
- metadata.setSinkClass(PartialStringMessageSink.class);
- }
- else
- {
- throw new RuntimeException(
- "Unable to add " + handler.getClass().getName() + " with type " + clazz + ": only supported types byte[], " + ByteBuffer.class.getName() +
- ", " + String.class.getName());
- }
-
- // Register the Metadata as a MessageHandler.
- registerMessageHandler(clazz, handler, basicType, metadata);
- }
- catch (NoSuchMethodException e)
- {
- throw new IllegalStateException("Unable to find method", e);
- }
- catch (IllegalAccessException e)
- {
- throw new IllegalStateException("Unable to access " + handler.getClass().getName(), e);
- }
+ // Register the Metadata as a MessageHandler.
+ registerMessageHandler(clazz, handler, basicType, metadata);
}
public void addMessageHandler(Class clazz, MessageHandler.Whole handler)
{
- try
+ MethodHolder methodHolder = new JakartaMessageWholeMethodHolder<>(handler);
+
+ if (PongMessage.class.isAssignableFrom(clazz))
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(MessageHandler.Whole.class, "onMessage", MethodType.methodType(void.class, Object.class))
- .bindTo(handler);
-
- if (PongMessage.class.isAssignableFrom(clazz))
- {
- assertBasicTypeNotRegistered(OpCode.PONG, handler);
- this.pongHandle = methodHandle;
- registerMessageHandler(OpCode.PONG, clazz, handler, null);
- return;
- }
-
- AvailableDecoders availableDecoders = session.getDecoders();
- RegisteredDecoder registeredDecoder = availableDecoders.getFirstRegisteredDecoder(clazz);
- if (registeredDecoder == null)
- throw new IllegalStateException("Unable to find Decoder for type: " + clazz);
-
- // Create the message metadata specific to the MessageHandler type.
- JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
- metadata.setMethodHandle(methodHandle);
- byte basicType;
- if (registeredDecoder.implementsInterface(Decoder.Binary.class))
- {
- basicType = OpCode.BINARY;
- metadata.setRegisteredDecoders(availableDecoders.getBinaryDecoders(clazz));
- metadata.setSinkClass(DecodedBinaryMessageSink.class);
- }
- else if (registeredDecoder.implementsInterface(Decoder.BinaryStream.class))
- {
- basicType = OpCode.BINARY;
- metadata.setRegisteredDecoders(availableDecoders.getBinaryStreamDecoders(clazz));
- metadata.setSinkClass(DecodedBinaryStreamMessageSink.class);
- }
- else if (registeredDecoder.implementsInterface(Decoder.Text.class))
- {
- basicType = OpCode.TEXT;
- metadata.setRegisteredDecoders(availableDecoders.getTextDecoders(clazz));
- metadata.setSinkClass(DecodedTextMessageSink.class);
- }
- else if (registeredDecoder.implementsInterface(Decoder.TextStream.class))
- {
- basicType = OpCode.TEXT;
- metadata.setRegisteredDecoders(availableDecoders.getTextStreamDecoders(clazz));
- metadata.setSinkClass(DecodedTextStreamMessageSink.class);
- }
- else
- {
- throw new RuntimeException("Unable to add " + handler.getClass().getName() + ": type " + clazz + " is unrecognized by declared decoders");
- }
-
- // Register the Metadata as a MessageHandler.
- registerMessageHandler(clazz, handler, basicType, metadata);
+ assertBasicTypeNotRegistered(OpCode.PONG, handler);
+ this.pongHandle = methodHolder;
+ registerMessageHandler(OpCode.PONG, clazz, handler, null);
+ return;
}
- catch (NoSuchMethodException e)
+
+ AvailableDecoders availableDecoders = session.getDecoders();
+ RegisteredDecoder registeredDecoder = availableDecoders.getFirstRegisteredDecoder(clazz);
+ if (registeredDecoder == null)
+ throw new IllegalStateException("Unable to find Decoder for type: " + clazz);
+
+ // Create the message metadata specific to the MessageHandler type.
+ JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
+ metadata.setMethodHolder(methodHolder);
+ byte basicType;
+ if (registeredDecoder.implementsInterface(Decoder.Binary.class))
{
- throw new IllegalStateException("Unable to find method", e);
+ basicType = OpCode.BINARY;
+ metadata.setRegisteredDecoders(availableDecoders.getBinaryDecoders(clazz));
+ metadata.setSinkClass(DecodedBinaryMessageSink.class);
}
- catch (IllegalAccessException e)
+ else if (registeredDecoder.implementsInterface(Decoder.BinaryStream.class))
{
- throw new IllegalStateException("Unable to access " + handler.getClass().getName(), e);
+ basicType = OpCode.BINARY;
+ metadata.setRegisteredDecoders(availableDecoders.getBinaryStreamDecoders(clazz));
+ metadata.setSinkClass(DecodedBinaryStreamMessageSink.class);
}
+ else if (registeredDecoder.implementsInterface(Decoder.Text.class))
+ {
+ basicType = OpCode.TEXT;
+ metadata.setRegisteredDecoders(availableDecoders.getTextDecoders(clazz));
+ metadata.setSinkClass(DecodedTextMessageSink.class);
+ }
+ else if (registeredDecoder.implementsInterface(Decoder.TextStream.class))
+ {
+ basicType = OpCode.TEXT;
+ metadata.setRegisteredDecoders(availableDecoders.getTextStreamDecoders(clazz));
+ metadata.setSinkClass(DecodedTextStreamMessageSink.class);
+ }
+ else
+ {
+ throw new RuntimeException("Unable to add " + handler.getClass().getName() + ": type " + clazz + " is unrecognized by declared decoders");
+ }
+
+ // Register the Metadata as a MessageHandler.
+ registerMessageHandler(clazz, handler, basicType, metadata);
}
private void assertBasicTypeNotRegistered(byte basicWebSocketType, MessageHandler replacement)
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
index 80e1158f2ab..11022f83bd2 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketFrameHandlerFactory.java
@@ -52,25 +52,11 @@ import org.eclipse.jetty.websocket.core.messages.PartialByteArrayMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.PartialStringMessageSink;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.eclipse.jetty.websocket.core.util.ReflectUtils;
public abstract class JakartaWebSocketFrameHandlerFactory
{
- private static final MethodHandle FILTER_RETURN_TYPE_METHOD;
-
- static
- {
- try
- {
- FILTER_RETURN_TYPE_METHOD = getServerMethodHandleLookup()
- .findVirtual(JakartaWebSocketSession.class, "filterReturnType", MethodType.methodType(void.class, Object.class));
- }
- catch (Throwable e)
- {
- throw new RuntimeException(e);
- }
- }
-
static InvokerUtils.Arg[] getArgsFor(Class> objectType)
{
return new InvokerUtils.Arg[]{new InvokerUtils.Arg(Session.class), new InvokerUtils.Arg(objectType).required()};
@@ -135,10 +121,10 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (metadata == null)
return null;
- MethodHandle openHandle = metadata.getOpenHandle();
- MethodHandle closeHandle = metadata.getCloseHandle();
- MethodHandle errorHandle = metadata.getErrorHandle();
- MethodHandle pongHandle = metadata.getPongHandle();
+ MethodHolder openHandle = MethodHolder.from(metadata.getOpenHandle());
+ MethodHolder closeHandle = MethodHolder.from(metadata.getCloseHandle());
+ MethodHolder errorHandle = MethodHolder.from(metadata.getErrorHandle());
+ MethodHolder pongHandle = MethodHolder.from(metadata.getPongHandle());
JakartaWebSocketMessageMetadata textMetadata = JakartaWebSocketMessageMetadata.copyOf(metadata.getTextMetadata());
JakartaWebSocketMessageMetadata binaryMetadata = JakartaWebSocketMessageMetadata.copyOf(metadata.getBinaryMetadata());
@@ -156,9 +142,9 @@ public abstract class JakartaWebSocketFrameHandlerFactory
pongHandle = bindTemplateVariables(pongHandle, namedVariables, pathParams);
if (textMetadata != null)
- textMetadata.setMethodHandle(bindTemplateVariables(textMetadata.getMethodHandle(), namedVariables, pathParams));
+ textMetadata.setMethodHolder(bindTemplateVariables(textMetadata.getMethodHolder(), namedVariables, pathParams));
if (binaryMetadata != null)
- binaryMetadata.setMethodHandle(bindTemplateVariables(binaryMetadata.getMethodHandle(), namedVariables, pathParams));
+ binaryMetadata.setMethodHolder(bindTemplateVariables(binaryMetadata.getMethodHolder(), namedVariables, pathParams));
}
openHandle = InvokerUtils.bindTo(openHandle, endpoint);
@@ -190,15 +176,15 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (AbstractDecodedMessageSink.class.isAssignableFrom(msgMetadata.getSinkClass()))
{
MethodHandle ctorHandle = lookup.findConstructor(msgMetadata.getSinkClass(),
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, List.class));
+ MethodType.methodType(void.class, CoreSession.class, MethodHolder.class, List.class));
List registeredDecoders = msgMetadata.getRegisteredDecoders();
- return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHandle(), registeredDecoders);
+ return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHolder(), registeredDecoders);
}
else
{
MethodHandle ctorHandle = lookup.findConstructor(msgMetadata.getSinkClass(),
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, boolean.class));
- return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHandle(), true);
+ MethodType.methodType(void.class, CoreSession.class, MethodHolder.class, boolean.class));
+ return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgMetadata.getMethodHolder(), true);
}
}
catch (NoSuchMethodException e)
@@ -219,23 +205,19 @@ public abstract class JakartaWebSocketFrameHandlerFactory
}
}
- public static MethodHandle wrapNonVoidReturnType(MethodHandle handle, JakartaWebSocketSession session)
+ static MethodHolder wrapNonVoidReturnType(MethodHolder handle, JakartaWebSocketSession session)
{
if (handle == null)
return null;
- if (handle.type().returnType() == Void.TYPE)
+ if (handle.returnType() == Void.TYPE)
return handle;
- // Technique from https://stackoverflow.com/questions/48505787/methodhandle-with-general-non-void-return-filter
-
- // Change the return type of the to be Object so it will match exact with JakartaWebSocketSession.filterReturnType(Object)
- handle = handle.asType(handle.type().changeReturnType(Object.class));
-
- // Filter the method return type to a call to JakartaWebSocketSession.filterReturnType() bound to this session
- handle = MethodHandles.filterReturnValue(handle, FILTER_RETURN_TYPE_METHOD.bindTo(session));
-
- return handle;
+ return args ->
+ {
+ session.filterReturnType(handle.invoke(args));
+ return null;
+ };
}
private MethodHandle toMethodHandle(MethodHandles.Lookup lookup, Method method)
@@ -252,7 +234,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
protected JakartaWebSocketFrameHandlerMetadata createEndpointMetadata(EndpointConfig endpointConfig)
{
- JakartaWebSocketFrameHandlerMetadata metadata = new JakartaWebSocketFrameHandlerMetadata(endpointConfig, container.getWebSocketComponents());
+ JakartaWebSocketFrameHandlerMetadata metadata = new JakartaWebSocketFrameHandlerMetadata(endpointConfig, components);
MethodHandles.Lookup lookup = getServerMethodHandleLookup();
Method openMethod = ReflectUtils.findMethod(Endpoint.class, "onOpen", Session.class, EndpointConfig.class);
@@ -360,7 +342,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (methodHandle != null)
{
msgMetadata.setSinkClass(PartialStringMessageSink.class);
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
metadata.setTextMetadata(msgMetadata, onMsg);
return true;
}
@@ -370,7 +352,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (methodHandle != null)
{
msgMetadata.setSinkClass(PartialByteBufferMessageSink.class);
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
metadata.setBinaryMetadata(msgMetadata, onMsg);
return true;
}
@@ -380,7 +362,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
if (methodHandle != null)
{
msgMetadata.setSinkClass(PartialByteArrayMessageSink.class);
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
metadata.setBinaryMetadata(msgMetadata, onMsg);
return true;
}
@@ -423,7 +405,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
objectType = decoder.objectType;
}
MethodHandle methodHandle = getMethodHandle.apply(getArgsFor(objectType));
- msgMetadata.setMethodHandle(methodHandle);
+ msgMetadata.setMethodHolder(MethodHolder.from(methodHandle));
// Set the sinkClass and then set the MessageMetadata on the FrameHandlerMetadata
if (interfaceType.equals(Decoder.Text.class))
@@ -508,7 +490,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
* have been statically assigned a converted value (and removed from the resulting {@link MethodHandle#type()}, or null if
* no {@code target} MethodHandle was provided.
*/
- public static MethodHandle bindTemplateVariables(MethodHandle target, String[] namedVariables, Map templateValues)
+ public static MethodHolder bindTemplateVariables(MethodHolder target, String[] namedVariables, Map templateValues)
{
if (target == null)
{
@@ -517,7 +499,7 @@ public abstract class JakartaWebSocketFrameHandlerFactory
final int IDX = 1;
- MethodHandle retHandle = target;
+ MethodHolder retHandle = target;
if ((templateValues == null) || (templateValues.isEmpty()))
{
@@ -527,54 +509,54 @@ public abstract class JakartaWebSocketFrameHandlerFactory
for (String variableName : namedVariables)
{
String strValue = templateValues.get(variableName);
- Class> type = retHandle.type().parameterType(IDX);
+ Class> type = retHandle.parameterType(IDX);
try
{
if (String.class.isAssignableFrom(type))
{
- retHandle = MethodHandles.insertArguments(retHandle, IDX, strValue);
+ retHandle = retHandle.bindTo(strValue, IDX);
}
else if (Integer.class.isAssignableFrom(type) || Integer.TYPE.isAssignableFrom(type))
{
Integer intValue = Integer.parseInt(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, intValue);
+ retHandle = retHandle.bindTo(intValue, IDX);
}
else if (Long.class.isAssignableFrom(type) || Long.TYPE.isAssignableFrom(type))
{
Long longValue = Long.parseLong(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, longValue);
+ retHandle = retHandle.bindTo(longValue, IDX);
}
else if (Short.class.isAssignableFrom(type) || Short.TYPE.isAssignableFrom(type))
{
Short shortValue = Short.parseShort(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, shortValue);
+ retHandle = retHandle.bindTo(shortValue, IDX);
}
else if (Float.class.isAssignableFrom(type) || Float.TYPE.isAssignableFrom(type))
{
Float floatValue = Float.parseFloat(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, floatValue);
+ retHandle = retHandle.bindTo(floatValue, IDX);
}
else if (Double.class.isAssignableFrom(type) || Double.TYPE.isAssignableFrom(type))
{
Double doubleValue = Double.parseDouble(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, doubleValue);
+ retHandle = retHandle.bindTo(doubleValue, IDX);
}
else if (Boolean.class.isAssignableFrom(type) || Boolean.TYPE.isAssignableFrom(type))
{
Boolean boolValue = Boolean.parseBoolean(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, boolValue);
+ retHandle = retHandle.bindTo(boolValue, IDX);
}
else if (Character.class.isAssignableFrom(type) || Character.TYPE.isAssignableFrom(type))
{
if (strValue.length() != 1)
throw new IllegalArgumentException("Invalid Size");
Character charValue = strValue.charAt(0);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, charValue);
+ retHandle = retHandle.bindTo(charValue, IDX);
}
else if (Byte.class.isAssignableFrom(type) || Byte.TYPE.isAssignableFrom(type))
{
Byte b = Byte.parseByte(strValue);
- retHandle = MethodHandles.insertArguments(retHandle, IDX, b);
+ retHandle = retHandle.bindTo(b, IDX);
}
else
{
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java
index 891c56e22c0..480ec3e89aa 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/JakartaWebSocketMessageMetadata.java
@@ -13,15 +13,15 @@
package org.eclipse.jetty.ee9.websocket.jakarta.common;
-import java.lang.invoke.MethodHandle;
import java.util.List;
import org.eclipse.jetty.ee9.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class JakartaWebSocketMessageMetadata
{
- private MethodHandle methodHandle;
+ private MethodHolder methodHolder;
private Class extends MessageSink> sinkClass;
private List registeredDecoders;
@@ -34,7 +34,7 @@ public class JakartaWebSocketMessageMetadata
return null;
JakartaWebSocketMessageMetadata copy = new JakartaWebSocketMessageMetadata();
- copy.methodHandle = metadata.methodHandle;
+ copy.methodHolder = metadata.methodHolder;
copy.sinkClass = metadata.sinkClass;
copy.registeredDecoders = metadata.registeredDecoders;
copy.maxMessageSize = metadata.maxMessageSize;
@@ -58,14 +58,14 @@ public class JakartaWebSocketMessageMetadata
this.maxMessageSizeSet = true;
}
- public MethodHandle getMethodHandle()
+ public MethodHolder getMethodHolder()
{
- return methodHandle;
+ return methodHolder;
}
- public void setMethodHandle(MethodHandle methodHandle)
+ public void setMethodHolder(MethodHolder methodHolder)
{
- this.methodHandle = methodHandle;
+ this.methodHolder = methodHolder;
}
public Class extends MessageSink> getSinkClass()
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java
index 94afefa5b98..194b08a9499 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/AbstractDecodedMessageSink.java
@@ -13,7 +13,6 @@
package org.eclipse.jetty.ee9.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
import java.util.List;
import java.util.stream.Collectors;
@@ -25,6 +24,7 @@ import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,12 +32,12 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
private static final Logger LOG = LoggerFactory.getLogger(AbstractDecodedMessageSink.class);
- private final MethodHandle _methodHandle;
+ private final MethodHolder _methodHolder;
private final MessageSink _messageSink;
- public AbstractDecodedMessageSink(CoreSession coreSession, MethodHandle methodHandle)
+ public AbstractDecodedMessageSink(CoreSession coreSession, MethodHolder methodHolder)
{
- _methodHandle = methodHandle;
+ _methodHolder = methodHolder;
try
{
@@ -58,7 +58,7 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
try
{
- _methodHandle.invoke(message);
+ _methodHolder.invoke(message);
}
catch (Throwable t)
{
@@ -67,7 +67,7 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
}
/**
- * @return a message sink which will first decode the message then pass it to {@link #_methodHandle}.
+ * @return a message sink which will first decode the message then pass it to {@link #_methodHolder}.
* @throws Exception for any error in creating the message sink.
*/
abstract MessageSink newMessageSink(CoreSession coreSession) throws Exception;
@@ -90,9 +90,9 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
protected final List _decoders;
- public Basic(CoreSession coreSession, MethodHandle methodHandle, List decoders)
+ public Basic(CoreSession coreSession, MethodHolder methodHolder, List decoders)
{
- super(coreSession, methodHandle);
+ super(coreSession, methodHolder);
if (decoders.isEmpty())
throw new IllegalArgumentException("Require at least one decoder for " + this.getClass());
_decoders = decoders.stream()
@@ -105,9 +105,9 @@ public abstract class AbstractDecodedMessageSink implements MessageSink
{
protected final T _decoder;
- public Stream(CoreSession coreSession, MethodHandle methodHandle, List decoders)
+ public Stream(CoreSession coreSession, MethodHolder methodHolder, List decoders)
{
- super(coreSession, methodHandle);
+ super(coreSession, methodHolder);
if (decoders.size() != 1)
throw new IllegalArgumentException("Require exactly one decoder for " + this.getClass());
_decoder = decoders.get(0).getInstance();
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
index 1eab5c76a87..a82280eab4b 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSink.java
@@ -13,20 +13,19 @@
package org.eclipse.jetty.ee9.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.nio.ByteBuffer;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee9.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee9.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.ByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,18 +33,23 @@ public class DecodedBinaryMessageSink extends AbstractDecodedMessageSink.Basi
{
private static final Logger LOG = LoggerFactory.getLogger(DecodedBinaryMessageSink.class);
- public DecodedBinaryMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedBinaryMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
MessageSink newMessageSink(CoreSession coreSession) throws Exception
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(DecodedBinaryMessageSink.class, "onWholeMessage", MethodType.methodType(void.class, ByteBuffer.class))
- .bindTo(this);
- return new ByteBufferMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onWholeMessage((ByteBuffer)args[0]);
+ return null;
+ };
+
+ return new ByteBufferMessageSink(coreSession, methodHolder, true);
}
public void onWholeMessage(ByteBuffer wholeMessage)
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
index d7d07ad4859..3d9e41af5d8 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSink.java
@@ -15,34 +15,38 @@ package org.eclipse.jetty.ee9.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee9.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee9.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.InputStreamMessageSink;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class DecodedBinaryStreamMessageSink extends AbstractDecodedMessageSink.Stream>
{
- public DecodedBinaryStreamMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedBinaryStreamMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
- MessageSink newMessageSink(CoreSession coreSession) throws Exception
+ MessageSink newMessageSink(CoreSession coreSession)
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(DecodedBinaryStreamMessageSink.class, "onStreamStart", MethodType.methodType(void.class, InputStream.class))
- .bindTo(this);
- return new InputStreamMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onStreamStart((InputStream)args[0]);
+ return null;
+ };
+
+ return new InputStreamMessageSink(coreSession, methodHolder, true);
}
public void onStreamStart(InputStream stream)
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSink.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSink.java
index e7091d4596e..b540ba57188 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSink.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSink.java
@@ -13,19 +13,18 @@
package org.eclipse.jetty.ee9.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee9.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee9.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
import org.eclipse.jetty.websocket.core.messages.StringMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,18 +32,23 @@ public class DecodedTextMessageSink extends AbstractDecodedMessageSink.Basic<
{
private static final Logger LOG = LoggerFactory.getLogger(DecodedTextMessageSink.class);
- public DecodedTextMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedTextMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
- MessageSink newMessageSink(CoreSession coreSession) throws NoSuchMethodException, IllegalAccessException
+ MessageSink newMessageSink(CoreSession coreSession)
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(getClass(), "onMessage", MethodType.methodType(void.class, String.class))
- .bindTo(this);
- return new StringMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onMessage((String)args[0]);
+ return null;
+ };
+
+ return new StringMessageSink(coreSession, methodHolder, true);
}
public void onMessage(String wholeMessage)
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
index 47993416cf1..eee163b2b74 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/main/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSink.java
@@ -15,34 +15,38 @@ package org.eclipse.jetty.ee9.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.Reader;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.WrongMethodTypeException;
import java.util.List;
import jakarta.websocket.CloseReason;
import jakarta.websocket.DecodeException;
import jakarta.websocket.Decoder;
-import org.eclipse.jetty.ee9.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee9.websocket.jakarta.common.decoders.RegisteredDecoder;
import org.eclipse.jetty.websocket.core.CoreSession;
import org.eclipse.jetty.websocket.core.exception.CloseException;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
import org.eclipse.jetty.websocket.core.messages.ReaderMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public class DecodedTextStreamMessageSink extends AbstractDecodedMessageSink.Stream>
{
- public DecodedTextStreamMessageSink(CoreSession session, MethodHandle methodHandle, List decoders)
+ public DecodedTextStreamMessageSink(CoreSession session, MethodHolder methodHolder, List decoders)
{
- super(session, methodHandle, decoders);
+ super(session, methodHolder, decoders);
}
@Override
- MessageSink newMessageSink(CoreSession coreSession) throws Exception
+ MessageSink newMessageSink(CoreSession coreSession)
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(DecodedTextStreamMessageSink.class, "onStreamStart", MethodType.methodType(void.class, Reader.class))
- .bindTo(this);
- return new ReaderMessageSink(coreSession, methodHandle, true);
+ MethodHolder methodHolder = args ->
+ {
+ if (args.length != 1)
+ throw new WrongMethodTypeException(String.format("Expected %s params but had %s", 1, args.length));
+ onStreamStart((Reader)args[0]);
+ return null;
+ };
+
+ return new ReaderMessageSink(coreSession, methodHolder, true);
}
public void onStreamStart(Reader reader)
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/AbstractMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/AbstractMessageSinkTest.java
index e9b3cf0b186..dc245da8720 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/AbstractMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/AbstractMessageSinkTest.java
@@ -23,6 +23,7 @@ import jakarta.websocket.Decoder;
import org.eclipse.jetty.ee9.websocket.jakarta.common.AbstractSessionTest;
import org.eclipse.jetty.ee9.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.ee9.websocket.jakarta.common.decoders.RegisteredDecoder;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
public abstract class AbstractMessageSinkTest extends AbstractSessionTest
{
@@ -43,7 +44,7 @@ public abstract class AbstractMessageSinkTest extends AbstractSessionTest
return List.of(new RegisteredDecoder(clazz, interfaceType, objectType, ClientEndpointConfig.Builder.create().build(), components));
}
- public MethodHandle getAcceptHandle(Consumer copy, Class type)
+ public MethodHolder getAcceptHandle(Consumer copy, Class type)
{
try
{
@@ -51,7 +52,7 @@ public abstract class AbstractMessageSinkTest extends AbstractSessionTest
String name = "accept";
MethodType methodType = MethodType.methodType(void.class, type);
MethodHandle handle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup().findVirtual(refc, name, methodType);
- return handle.bindTo(copy);
+ return MethodHolder.from(handle.bindTo(copy));
}
catch (NoSuchMethodException | IllegalAccessException e)
{
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
index aaa05b69ccd..9a6c19bded0 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryMessageSinkTest.java
@@ -13,7 +13,6 @@
package org.eclipse.jetty.ee9.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -31,6 +30,7 @@ import org.eclipse.jetty.ee9.websocket.jakarta.common.decoders.RegisteredDecoder
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -45,7 +45,7 @@ public class DecodedBinaryMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(AbstractSessionTest.session.getCoreSession(), copyHandle, decoders);
@@ -67,7 +67,7 @@ public class DecodedBinaryMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedBinaryMessageSink sink = new DecodedBinaryMessageSink<>(AbstractSessionTest.session.getCoreSession(), copyHandle, decoders);
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
index 47863ff3271..20ab7969de1 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedBinaryStreamMessageSinkTest.java
@@ -15,7 +15,6 @@ package org.eclipse.jetty.ee9.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.invoke.MethodHandle;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -33,6 +32,7 @@ import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -47,7 +47,7 @@ public class DecodedBinaryStreamMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedBinaryStreamMessageSink sink = new DecodedBinaryStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
@@ -69,7 +69,7 @@ public class DecodedBinaryStreamMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedCalendarCopy copy = new DecodedCalendarCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Calendar.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Calendar.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedBinaryStreamMessageSink sink = new DecodedBinaryStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
index f4c08ab3172..48a7d980bb5 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextMessageSinkTest.java
@@ -13,7 +13,6 @@
package org.eclipse.jetty.ee9.websocket.jakarta.common.messages;
-import java.lang.invoke.MethodHandle;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -31,6 +30,7 @@ import org.eclipse.jetty.ee9.websocket.jakarta.common.decoders.RegisteredDecoder
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -45,7 +45,7 @@ public class DecodedTextMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedTextMessageSink sink = new DecodedTextMessageSink<>(session.getCoreSession(), copyHandle, decoders);
@@ -62,7 +62,7 @@ public class DecodedTextMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedTextMessageSink sink = new DecodedTextMessageSink<>(session.getCoreSession(), copyHandle, decoders);
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
index 4dd8cd533ee..b24c5f8d1c0 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/DecodedTextStreamMessageSinkTest.java
@@ -15,7 +15,6 @@ package org.eclipse.jetty.ee9.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.Reader;
-import java.lang.invoke.MethodHandle;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
@@ -34,6 +33,7 @@ import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -48,7 +48,7 @@ public class DecodedTextStreamMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
@@ -65,7 +65,7 @@ public class DecodedTextStreamMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
DecodedDateCopy copy = new DecodedDateCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Date.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Date.class);
List decoders = toRegisteredDecoderList(GmtDecoder.class, Calendar.class);
DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), copyHandle, decoders);
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
index 56ccec6089a..137c74fb15d 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/InputStreamMessageSinkTest.java
@@ -16,7 +16,6 @@ package org.eclipse.jetty.ee9.websocket.jakarta.common.messages;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.invoke.MethodHandle;
import java.nio.ByteBuffer;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
@@ -33,6 +32,7 @@ import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
import org.eclipse.jetty.websocket.core.messages.InputStreamMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -46,7 +46,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
public void testInputStream1Message1Frame() throws InterruptedException, ExecutionException, TimeoutException
{
InputStreamCopy copy = new InputStreamCopy();
- MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, InputStream.class);
InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle, true);
FutureCallback finCallback = new FutureCallback();
@@ -63,7 +63,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
public void testInputStream2Messages2Frames() throws InterruptedException, ExecutionException, TimeoutException
{
InputStreamCopy copy = new InputStreamCopy();
- MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, InputStream.class);
InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle, true);
FutureCallback fin1Callback = new FutureCallback();
@@ -91,7 +91,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
public void testInputStream1Message3Frames() throws InterruptedException, ExecutionException, TimeoutException
{
InputStreamCopy copy = new InputStreamCopy();
- MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, InputStream.class);
InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
@@ -113,7 +113,7 @@ public class InputStreamMessageSinkTest extends AbstractMessageSinkTest
public void testInputStream1Message4FramesEmptyFin() throws InterruptedException, ExecutionException, TimeoutException
{
InputStreamCopy copy = new InputStreamCopy();
- MethodHandle copyHandle = getAcceptHandle(copy, InputStream.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, InputStream.class);
InputStreamMessageSink sink = new InputStreamMessageSink(AbstractSessionTest.session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/ReaderMessageSinkTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
index 795422ecc4f..e51638d6ec2 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/messages/ReaderMessageSinkTest.java
@@ -16,7 +16,6 @@ package org.eclipse.jetty.ee9.websocket.jakarta.common.messages;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
-import java.lang.invoke.MethodHandle;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@@ -28,6 +27,7 @@ import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.OpCode;
import org.eclipse.jetty.websocket.core.messages.ReaderMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -40,7 +40,7 @@ public class ReaderMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
ReaderCopy copy = new ReaderCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Reader.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Reader.class);
ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback finCallback = new FutureCallback();
@@ -56,7 +56,7 @@ public class ReaderMessageSinkTest extends AbstractMessageSinkTest
{
CompletableFuture copyFuture = new CompletableFuture<>();
ReaderCopy copy = new ReaderCopy(copyFuture);
- MethodHandle copyHandle = getAcceptHandle(copy, Reader.class);
+ MethodHolder copyHandle = getAcceptHandle(copy, Reader.class);
ReaderMessageSink sink = new ReaderMessageSink(session.getCoreSession(), copyHandle, true);
FutureCallback callback1 = new FutureCallback();
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java
index 8d8e4373285..fc2525e5d41 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-common/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/common/util/InvokerUtilsStaticParamsTest.java
@@ -23,6 +23,7 @@ import jakarta.websocket.Session;
import org.eclipse.jetty.ee9.websocket.jakarta.common.JakartaWebSocketFrameHandlerFactory;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.eclipse.jetty.websocket.core.util.ReflectUtils;
import org.junit.jupiter.api.Test;
@@ -57,6 +58,12 @@ public class InvokerUtilsStaticParamsTest
private static MethodHandles.Lookup lookup = MethodHandles.lookup();
+ private MethodHolder getMethodHolder(Method method, String[] namedVariables, InvokerUtils.Arg... args)
+ {
+ MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables, args);
+ return MethodHolder.from(methodHandle);
+ }
+
@Test
public void testOnlyParamString() throws Throwable
{
@@ -70,21 +77,21 @@ public class InvokerUtilsStaticParamsTest
// Raw Calling Args - none specified
// Get basic method handle (without a instance to call against) - this is what the metadata stores
- MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables);
+ MethodHolder methodHolder = getMethodHolder(method, namedVariables);
// Some point later an actual instance is needed, which has static named parameters
Map templateValues = new HashMap<>();
templateValues.put("fruit", "pear");
// Bind the static values, in same order as declared
- methodHandle = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHandle, namedVariables, templateValues);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHolder, namedVariables, templateValues);
// Assign an instance to call.
Foo foo = new Foo();
- methodHandle = methodHandle.bindTo(foo);
+ methodHolder = methodHolder.bindTo(foo);
// Call method against instance
- String result = (String)methodHandle.invoke();
+ String result = (String)methodHolder.invoke();
assertThat("Result", result, is("onFruit('pear')"));
}
@@ -99,21 +106,21 @@ public class InvokerUtilsStaticParamsTest
};
// Get basic method handle (without a instance to call against) - this is what the metadata stores
- MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables);
+ MethodHolder methodHolder = getMethodHolder(method, namedVariables);
// Some point later an actual instance is needed, which has static named parameters
Map templateValues = new HashMap<>();
templateValues.put("count", "2222");
// Bind the static values for the variables, in same order as the variables were declared
- methodHandle = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHandle, namedVariables, templateValues);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHolder, namedVariables, templateValues);
// Assign an instance to call.
Foo foo = new Foo();
- methodHandle = methodHandle.bindTo(foo);
+ methodHolder = methodHolder.bindTo(foo);
// Call method against instance
- String result = (String)methodHandle.invoke();
+ String result = (String)methodHolder.invoke();
assertThat("Result", result, is("onCount(2222)"));
}
@@ -130,21 +137,21 @@ public class InvokerUtilsStaticParamsTest
final InvokerUtils.Arg ARG_LABEL = new InvokerUtils.Arg(String.class).required();
// Get basic method handle (without a instance to call against) - this is what the metadata stores
- MethodHandle methodHandle = InvokerUtils.mutatedInvoker(lookup, Foo.class, method, new NameParamIdentifier(), namedVariables, ARG_LABEL);
+ MethodHolder methodHolder = getMethodHolder(method, namedVariables, ARG_LABEL);
// Some point later an actual instance is needed, which has static named parameters
Map templateValues = new HashMap<>();
templateValues.put("count", "444");
// Bind the static values for the variables, in same order as the variables were declared
- methodHandle = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHandle, namedVariables, templateValues);
+ methodHolder = JakartaWebSocketFrameHandlerFactory.bindTemplateVariables(methodHolder, namedVariables, templateValues);
// Assign an instance to call.
Foo foo = new Foo();
- methodHandle = methodHandle.bindTo(foo);
+ methodHolder = methodHolder.bindTo(foo);
// Call method against instance
- String result = (String)methodHandle.invoke("cherry");
+ String result = (String)methodHolder.invoke("cherry");
assertThat("Result", result, is("onLabeledCount('cherry', 444)"));
}
}
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/coders/DecoderTextStreamTest.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/coders/DecoderTextStreamTest.java
index eec22ab2f5b..2d666bbae69 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/coders/DecoderTextStreamTest.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jakarta-tests/src/test/java/org/eclipse/jetty/ee9/websocket/jakarta/tests/coders/DecoderTextStreamTest.java
@@ -33,6 +33,7 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.websocket.core.Frame;
import org.eclipse.jetty.websocket.core.WebSocketComponents;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -80,7 +81,7 @@ public class DecoderTextStreamTest extends AbstractClientSessionTest
});
List decoders = toRegisteredDecoderList(QuotesDecoder.class, Quotes.class);
- DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), quoteHandle, decoders);
+ DecodedTextStreamMessageSink sink = new DecodedTextStreamMessageSink<>(session.getCoreSession(), MethodHolder.from(quoteHandle), decoders);
List callbacks = new ArrayList<>();
FutureCallback finCallback = null;
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandler.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandler.java
index 6ef8af298cc..c8d5f0d7c96 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandler.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandler.java
@@ -13,9 +13,9 @@
package org.eclipse.jetty.ee9.websocket.common;
-import java.lang.invoke.MethodHandle;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
+import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.ee9.websocket.api.BatchMode;
@@ -42,6 +42,7 @@ import org.eclipse.jetty.websocket.core.exception.WebSocketException;
import org.eclipse.jetty.websocket.core.exception.WebSocketTimeoutException;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -61,16 +62,16 @@ public class JettyWebSocketFrameHandler implements FrameHandler
private final Object endpointInstance;
private final BatchMode batchMode;
private final AtomicBoolean closeNotified = new AtomicBoolean();
- private MethodHandle openHandle;
- private MethodHandle closeHandle;
- private MethodHandle errorHandle;
- private MethodHandle textHandle;
+ private MethodHolder openHandle;
+ private MethodHolder closeHandle;
+ private MethodHolder errorHandle;
+ private MethodHolder textHandle;
private final Class extends MessageSink> textSinkClass;
- private MethodHandle binaryHandle;
+ private MethodHolder binaryHandle;
private final Class extends MessageSink> binarySinkClass;
- private MethodHandle frameHandle;
- private MethodHandle pingHandle;
- private MethodHandle pongHandle;
+ private MethodHolder frameHandle;
+ private MethodHolder pingHandle;
+ private MethodHolder pongHandle;
private UpgradeRequest upgradeRequest;
private UpgradeResponse upgradeResponse;
@@ -85,12 +86,12 @@ public class JettyWebSocketFrameHandler implements FrameHandler
public JettyWebSocketFrameHandler(WebSocketContainer container,
Object endpointInstance,
- MethodHandle openHandle, MethodHandle closeHandle, MethodHandle errorHandle,
- MethodHandle textHandle, MethodHandle binaryHandle,
+ MethodHolder openHandle, MethodHolder closeHandle, MethodHolder errorHandle,
+ MethodHolder textHandle, MethodHolder binaryHandle,
Class extends MessageSink> textSinkClass,
Class extends MessageSink> binarySinkClass,
- MethodHandle frameHandle,
- MethodHandle pingHandle, MethodHandle pongHandle,
+ MethodHolder frameHandle,
+ MethodHolder pingHandle, MethodHolder pongHandle,
BatchMode batchMode,
Configuration.Customizer customizer)
{
@@ -163,15 +164,13 @@ public class JettyWebSocketFrameHandler implements FrameHandler
pingHandle = InvokerUtils.bindTo(pingHandle, session);
pongHandle = InvokerUtils.bindTo(pongHandle, session);
+ Executor executor = coreSession.getWebSocketComponents().getExecutor();
if (textHandle != null)
- textSink = JettyWebSocketFrameHandlerFactory.createMessageSink(textHandle, textSinkClass, session);
-
+ textSink = JettyWebSocketFrameHandlerFactory.createMessageSink(textHandle, textSinkClass, executor, session);
if (binaryHandle != null)
- binarySink = JettyWebSocketFrameHandlerFactory.createMessageSink(binaryHandle, binarySinkClass, session);
-
+ binarySink = JettyWebSocketFrameHandlerFactory.createMessageSink(binaryHandle, binarySinkClass, executor, session);
if (openHandle != null)
openHandle.invoke();
-
if (session.isOpen())
container.notifySessionListeners((listener) -> listener.onWebSocketSessionOpened(session));
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandlerFactory.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandlerFactory.java
index 51040f628a6..1b7cb920c85 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandlerFactory.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/main/java/org/eclipse/jetty/ee9/websocket/common/JettyWebSocketFrameHandlerFactory.java
@@ -27,6 +27,7 @@ import java.nio.ByteBuffer;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
import org.eclipse.jetty.ee9.websocket.api.BatchMode;
import org.eclipse.jetty.ee9.websocket.api.Frame;
@@ -58,6 +59,7 @@ import org.eclipse.jetty.websocket.core.messages.PartialStringMessageSink;
import org.eclipse.jetty.websocket.core.messages.ReaderMessageSink;
import org.eclipse.jetty.websocket.core.messages.StringMessageSink;
import org.eclipse.jetty.websocket.core.util.InvokerUtils;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.eclipse.jetty.websocket.core.util.ReflectUtils;
/**
@@ -165,16 +167,16 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
{
JettyWebSocketFrameHandlerMetadata metadata = getMetadata(endpointInstance.getClass());
- final MethodHandle openHandle = InvokerUtils.bindTo(metadata.getOpenHandle(), endpointInstance);
- final MethodHandle closeHandle = InvokerUtils.bindTo(metadata.getCloseHandle(), endpointInstance);
- final MethodHandle errorHandle = InvokerUtils.bindTo(metadata.getErrorHandle(), endpointInstance);
- final MethodHandle textHandle = InvokerUtils.bindTo(metadata.getTextHandle(), endpointInstance);
- final MethodHandle binaryHandle = InvokerUtils.bindTo(metadata.getBinaryHandle(), endpointInstance);
+ final MethodHolder openHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getOpenHandle()), endpointInstance);
+ final MethodHolder closeHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getCloseHandle()), endpointInstance);
+ final MethodHolder errorHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getErrorHandle()), endpointInstance);
+ final MethodHolder textHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getTextHandle()), endpointInstance);
+ final MethodHolder binaryHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getBinaryHandle()), endpointInstance);
final Class extends MessageSink> textSinkClass = metadata.getTextSink();
final Class extends MessageSink> binarySinkClass = metadata.getBinarySink();
- final MethodHandle frameHandle = InvokerUtils.bindTo(metadata.getFrameHandle(), endpointInstance);
- final MethodHandle pingHandle = InvokerUtils.bindTo(metadata.getPingHandle(), endpointInstance);
- final MethodHandle pongHandle = InvokerUtils.bindTo(metadata.getPongHandle(), endpointInstance);
+ final MethodHolder frameHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getFrameHandle()), endpointInstance);
+ final MethodHolder pingHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getPingHandle()), endpointInstance);
+ final MethodHolder pongHandle = InvokerUtils.bindTo(MethodHolder.from(metadata.getPongHandle()), endpointInstance);
BatchMode batchMode = metadata.getBatchMode();
// Decorate the endpointInstance while we are still upgrading for access to things like HttpSession.
@@ -191,7 +193,7 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
metadata);
}
- public static MessageSink createMessageSink(MethodHandle msgHandle, Class extends MessageSink> sinkClass, WebSocketSession session)
+ public static MessageSink createMessageSink(MethodHolder msgHandle, Class extends MessageSink> sinkClass, Executor executor, WebSocketSession session)
{
if (msgHandle == null)
return null;
@@ -202,7 +204,7 @@ public class JettyWebSocketFrameHandlerFactory extends ContainerLifeCycle
{
MethodHandles.Lookup lookup = JettyWebSocketFrameHandlerFactory.getServerMethodHandleLookup();
MethodHandle ctorHandle = lookup.findConstructor(sinkClass,
- MethodType.methodType(void.class, CoreSession.class, MethodHandle.class, boolean.class));
+ MethodType.methodType(void.class, CoreSession.class, MethodHolder.class, boolean.class));
return (MessageSink)ctorHandle.invoke(session.getCoreSession(), msgHandle, true);
}
catch (NoSuchMethodException e)
diff --git a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/OutgoingMessageCapture.java b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/OutgoingMessageCapture.java
index be891e1cb72..981b10560fa 100644
--- a/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/OutgoingMessageCapture.java
+++ b/jetty-ee9/jetty-ee9-websocket/jetty-ee9-websocket-jetty-common/src/test/java/org/eclipse/jetty/ee9/websocket/common/OutgoingMessageCapture.java
@@ -30,6 +30,7 @@ import org.eclipse.jetty.websocket.core.OpCode;
import org.eclipse.jetty.websocket.core.messages.ByteBufferMessageSink;
import org.eclipse.jetty.websocket.core.messages.MessageSink;
import org.eclipse.jetty.websocket.core.messages.StringMessageSink;
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -96,7 +97,7 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
String event = String.format("TEXT:fin=%b:len=%d", frame.isFin(), frame.getPayloadLength());
LOG.debug(event);
events.offer(event);
- messageSink = new StringMessageSink(this, wholeTextHandle, true);
+ messageSink = new StringMessageSink(this, MethodHolder.from(wholeTextHandle), true);
break;
}
case OpCode.BINARY:
@@ -104,7 +105,7 @@ public class OutgoingMessageCapture extends CoreSession.Empty implements CoreSes
String event = String.format("BINARY:fin=%b:len=%d", frame.isFin(), frame.getPayloadLength());
LOG.debug(event);
events.offer(event);
- messageSink = new ByteBufferMessageSink(this, wholeBinaryHandle, true);
+ messageSink = new ByteBufferMessageSink(this, MethodHolder.from(wholeBinaryHandle), true);
break;
}
case OpCode.CONTINUATION:
diff --git a/tests/jetty-jmh/pom.xml b/tests/jetty-jmh/pom.xml
index 035f1cff972..5ad89ec81b1 100644
--- a/tests/jetty-jmh/pom.xml
+++ b/tests/jetty-jmh/pom.xml
@@ -41,6 +41,14 @@
org.eclipse.jetty.toolchain
jetty-test-helper
+
+ org.eclipse.jetty.websocket
+ jetty-websocket-jetty-client
+
+
+ org.eclipse.jetty.websocket
+ jetty-websocket-jetty-server
+
org.openjdk.jmh
jmh-core
diff --git a/tests/jetty-jmh/src/main/java/org/eclipse/jetty/websocket/jmh/MethodHolderBenchmark.java b/tests/jetty-jmh/src/main/java/org/eclipse/jetty/websocket/jmh/MethodHolderBenchmark.java
new file mode 100644
index 00000000000..f96ae788e27
--- /dev/null
+++ b/tests/jetty-jmh/src/main/java/org/eclipse/jetty/websocket/jmh/MethodHolderBenchmark.java
@@ -0,0 +1,111 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.websocket.jmh;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.websocket.core.util.MethodHolder;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Threads;
+import org.openjdk.jmh.annotations.Warmup;
+import org.openjdk.jmh.infra.Blackhole;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+@State(Scope.Benchmark)
+@Threads(4)
+@Warmup(iterations = 7, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+@Measurement(iterations = 7, time = 500, timeUnit = TimeUnit.MILLISECONDS)
+public class MethodHolderBenchmark
+{
+ private MethodHandle methodHandle;
+ private MethodHolder methodHolderNonBinding;
+ private MethodHolder methodHolderBinding;
+
+ @Setup(Level.Trial)
+ public void setupTrial(Blackhole blackhole) throws Throwable
+ {
+ MethodType methodType = MethodType.methodType(void.class, Blackhole.class, String.class, String.class);
+ methodHandle = MethodHandles.lookup()
+ .findVirtual(MethodHolderBenchmark.class, "consume", methodType);
+ if (methodHandle == null)
+ throw new IllegalStateException();
+
+ methodHolderBinding = MethodHolder.from(methodHandle, true);
+ methodHolderBinding.bindTo(this);
+ methodHolderBinding.bindTo(Objects.requireNonNull(blackhole));
+
+ methodHolderNonBinding = MethodHolder.from(methodHandle, false);
+ methodHolderNonBinding.bindTo(this);
+ methodHolderNonBinding.bindTo(Objects.requireNonNull(blackhole));
+
+ methodHandle = methodHandle.bindTo(this);
+ methodHandle = methodHandle.bindTo(Objects.requireNonNull(blackhole));
+ }
+
+ public void consume(Blackhole blackhole, String a, String b)
+ {
+ blackhole.consume(a);
+ blackhole.consume(b);
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public void methodHandle() throws Throwable
+ {
+ methodHandle.invoke("test", "12");
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public void methodHolderNonBinding() throws Throwable
+ {
+ methodHolderNonBinding.invoke("test", "12");
+ }
+
+ @Benchmark
+ @BenchmarkMode({Mode.Throughput})
+ public void methodHolderBinding() throws Throwable
+ {
+ methodHolderBinding.invoke("test", "12");
+ }
+
+ public static void main(String[] args) throws RunnerException
+ {
+ Options opt = new OptionsBuilder()
+ .include(MethodHolderBenchmark.class.getSimpleName())
+ .warmupIterations(1)
+ .measurementIterations(5)
+ .forks(1)
+ .threads(1)
+ .build();
+
+ new Runner(opt).run();
+ }
+}
+
+