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 fa6349e1f117..979098405bd8 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 @@
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 CoreSession getCoreSession()
* 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 2d562c78fbf7..d9ac9549b0d4 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.ByteBufferCallbackAccumulator;
@@ -22,8 +20,8 @@
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 void accept(Frame frame, Callback callback)
if (frame.isFin() && (accumulator == null || accumulator.getLength() == 0))
{
byte[] buf = BufferUtil.toArray(payload);
- getMethodHandle().invoke(buf, 0, buf.length);
+ getMethodHolder().invoke(buf, 0, buf.length);
callback.succeeded();
autoDemand();
return;
@@ -92,7 +85,7 @@ public void accept(Frame frame, Callback callback)
// Do not complete twice the callback if the invocation fails.
callback = Callback.NOOP;
byte[] buf = accumulator.takeByteArray();
- getMethodHandle().invoke(buf, 0, buf.length);
+ getMethodHolder().invoke(buf, 0, buf.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 2783387b3381..41d1df5210f5 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.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 void accept(Frame frame, Callback callback)
// 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 void accept(Frame frame, Callback callback)
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 void fail(Throwable failure)
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 7deb4ed60d86..f3439f85e76f 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
@@ -26,6 +26,7 @@
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 +52,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 +75,7 @@ public void accept(Frame frame, final Callback callback)
{
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 72c65802387f..bbf826747cbc 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 c07b35484bcc..37da9c08c2c1 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 void accept(Frame frame, Callback callback)
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 5cdf0ebba02d..3ebe188d3fd8 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
@@ -19,6 +19,7 @@
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 +32,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 +47,7 @@ public void accept(Frame frame, Callback callback)
{
if (frame.hasPayload() || frame.isFin())
{
- invoke(getMethodHandle(), frame.getPayload(), frame.isFin(), callback);
+ invoke(getMethodHolder(), frame.getPayload(), frame.isFin(), callback);
autoDemand();
}
else
@@ -61,9 +62,9 @@ public void accept(Frame frame, Callback callback)
}
}
- 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 ba74c2c5f134..b3548ad83c39 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
@@ -20,6 +20,7 @@
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 +35,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 +56,12 @@ public void accept(Frame frame, Callback callback)
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 8f8e4f1759a1..fb6cc87f1e7f 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 e3bb1ded729a..66fff19726e4 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 void accept(Frame frame, Callback callback)
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/BindingMethodHolder.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/BindingMethodHolder.java
new file mode 100644
index 000000000000..b58f623a2158
--- /dev/null
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/BindingMethodHolder.java
@@ -0,0 +1,69 @@
+//
+// ========================================================================
+// 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;
+
+class BindingMethodHolder implements MethodHolder
+{
+ public MethodHandle _methodHandle;
+
+ public BindingMethodHolder(MethodHandle methodHandle)
+ {
+ _methodHandle = methodHandle;
+ }
+
+ @Override
+ public Object invoke(Object... args) throws Throwable
+ {
+ return MethodHolder.doInvoke(_methodHandle, args);
+ }
+
+ public MethodHandle getMethodHandler()
+ {
+ return _methodHandle;
+ }
+
+ public Object invoke(Object o1, Object o2) throws Throwable
+ {
+ return MethodHolder.doInvoke(_methodHandle, o1, o2);
+ }
+
+ @Override
+ public BindingMethodHolder 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();
+ }
+}
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 6fc71474e630..e8a6e6c68e81 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 Arg getParamArg(Method method, Class> paramType, int idx)
/**
* 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 000000000000..e699dcaa7b41
--- /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,105 @@
+//
+// ========================================================================
+// 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;
+
+/**
+ * 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";
+
+ static MethodHolder from(MethodHandle methodHandle)
+ {
+ String property = System.getProperty(METHOD_HOLDER_BINDING_PROPERTY);
+ return from(methodHandle, Boolean.parseBoolean(property));
+ }
+
+ static MethodHolder from(MethodHandle methodHandle, boolean binding)
+ {
+ if (methodHandle == null)
+ return null;
+ return binding ? new BindingMethodHolder(methodHandle) : new NonBindingMethodHolder(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 arg1, Object arg2) throws Throwable
+ {
+ return methodHandle.invoke(arg1, arg2);
+ }
+
+ 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);
+ }
+ }
+}
diff --git a/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/NonBindingMethodHolder.java b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/NonBindingMethodHolder.java
new file mode 100644
index 000000000000..b92fa4c6672f
--- /dev/null
+++ b/jetty-core/jetty-websocket/jetty-websocket-core-common/src/main/java/org/eclipse/jetty/websocket/core/util/NonBindingMethodHolder.java
@@ -0,0 +1,103 @@
+//
+// ========================================================================
+// 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.WrongMethodTypeException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * 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 NonBindingMethodHolder implements MethodHolder
+{
+ private final MethodHandle _methodHandle;
+ private final Object[] _parameters;
+ private final List _unboundParamIndexes = new ArrayList<>();
+
+ public NonBindingMethodHolder(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 MethodHolder.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 80d6cd4302dc..daa360a48227 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 a5448b74b45b..69cbd26ece22 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 @@
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 void testMaxMessageSize() throws Exception
@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 void testValidUtf8() throws Exception
@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 void testUtf8Continuation() throws Exception
@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 void testInvalidSingleFrameUtf8() throws Exception
@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 d304ef864ad2..902784fda5d5 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.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 JettyWebSocketFrameHandler(WebSocketContainer container, Object endpointI
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 void onOpen(CoreSession coreSession, Callback callback)
}
}
- 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 @@ private static MessageSink createMessageSink(Class extends MessageSink> sinkCl
{
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/JettyWebSocketFrameHandlerFactory.java b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerFactory.java
index b342d50233ac..bd438e1e55f3 100644
--- a/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerFactory.java
+++ b/jetty-core/jetty-websocket/jetty-websocket-jetty-common/src/main/java/org/eclipse/jetty/websocket/common/JettyWebSocketFrameHandlerFactory.java
@@ -46,6 +46,7 @@
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;
/**
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 4d9b6b3ef267..7eadef8f20be 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 479e90cb7797..04a524e58fa7 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 206eb603937e..cb9edd2c9add 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.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 void sendFrame(Frame frame, org.eclipse.jetty.util.Callback callback, boo
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 void sendFrame(Frame frame, org.eclipse.jetty.util.Callback callback, boo
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 000000000000..7b3e66f1849e
--- /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 000000000000..efe8bab30a87
--- /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 86f110b4ed69..a5fe95bfd44b 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
@@ -51,6 +51,7 @@
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 +63,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 +80,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 +148,10 @@ public void onOpen(CoreSession coreSession, Callback callback)
if (actualTextMetadata.isMaxMessageSizeSet())
session.setMaxTextMessageBufferSize(actualTextMetadata.getMaxMessageSize());
- MethodHandle methodHandle = actualTextMetadata.getMethodHandle();
+ MethodHolder methodHandle = actualTextMetadata.getMethodHolder();
methodHandle = InvokerUtils.bindTo(methodHandle, endpointInstance, endpointConfig, session);
methodHandle = JakartaWebSocketFrameHandlerFactory.wrapNonVoidReturnType(methodHandle, session);
- actualTextMetadata.setMethodHandle(methodHandle);
+ actualTextMetadata.setMethodHolder(methodHandle);
textSink = JakartaWebSocketFrameHandlerFactory.createMessageSink(session, actualTextMetadata);
textMetadata = actualTextMetadata;
@@ -162,10 +163,10 @@ public void onOpen(CoreSession coreSession, Callback callback)
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 +347,88 @@ public JakartaWebSocketMessageMetadata getTextMetadata()
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))
+ {
+ basicType = OpCode.BINARY;
+ metadata.setSinkClass(PartialByteArrayMessageSink.class);
+ }
+ else if (ByteBuffer.class.isAssignableFrom(clazz))
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(MessageHandler.Partial.class, "onMessage", MethodType.methodType(void.class, Object.class, boolean.class))
- .bindTo(handler);
-
- 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);
+ basicType = OpCode.BINARY;
+ metadata.setSinkClass(PartialByteBufferMessageSink.class);
}
- catch (NoSuchMethodException e)
+ else if (String.class.isAssignableFrom(clazz))
{
- throw new IllegalStateException("Unable to find method", e);
+ basicType = OpCode.TEXT;
+ metadata.setSinkClass(PartialStringMessageSink.class);
}
- catch (IllegalAccessException e)
+ else
{
- throw new IllegalStateException("Unable to access " + handler.getClass().getName(), e);
+ 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);
}
public void addMessageHandler(Class clazz, MessageHandler.Whole handler)
{
- try
- {
- 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;
- }
+ MethodHolder methodHolder = new JakartaMessageWholeMethodHolder<>(handler);
- AvailableDecoders availableDecoders = session.getDecoders();
- RegisteredDecoder registeredDecoder = availableDecoders.getFirstRegisteredDecoder(clazz);
- if (registeredDecoder == null)
- throw new IllegalStateException("Unable to find Decoder for type: " + clazz);
+ if (PongMessage.class.isAssignableFrom(clazz))
+ {
+ assertBasicTypeNotRegistered(OpCode.PONG, handler);
+ this.pongHandle = methodHolder;
+ registerMessageHandler(OpCode.PONG, clazz, handler, null);
+ return;
+ }
- // 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");
- }
+ AvailableDecoders availableDecoders = session.getDecoders();
+ RegisteredDecoder registeredDecoder = availableDecoders.getFirstRegisteredDecoder(clazz);
+ if (registeredDecoder == null)
+ throw new IllegalStateException("Unable to find Decoder for type: " + clazz);
- // Register the Metadata as a MessageHandler.
- registerMessageHandler(clazz, handler, basicType, metadata);
+ // Create the message metadata specific to the MessageHandler type.
+ JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
+ metadata.setMethodHolder(methodHolder);
+ 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);
}
- catch (NoSuchMethodException e)
+ else if (registeredDecoder.implementsInterface(Decoder.Text.class))
{
- throw new IllegalStateException("Unable to find method", e);
+ basicType = OpCode.TEXT;
+ metadata.setRegisteredDecoders(availableDecoders.getTextDecoders(clazz));
+ metadata.setSinkClass(DecodedTextMessageSink.class);
}
- catch (IllegalAccessException e)
+ else if (registeredDecoder.implementsInterface(Decoder.TextStream.class))
{
- throw new IllegalStateException("Unable to access " + handler.getClass().getName(), e);
+ 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 dd90ab38a138..afd8f383282d 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.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 JakartaWebSocketFrameHandler newJakartaWebSocketFrameHandler(Object endpo
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 JakartaWebSocketFrameHandler newJakartaWebSocketFrameHandler(Object endpo
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 static MessageSink createMessageSink(JakartaWebSocketSession session, Jak
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 static MessageSink createMessageSink(JakartaWebSocketSession session, Jak
}
}
- 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 @@ private boolean matchOnMessage(Method onMsg, JakartaWebSocketFrameHandlerMetadat
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 @@ private boolean matchOnMessage(Method onMsg, JakartaWebSocketFrameHandlerMetadat
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 @@ private boolean matchOnMessage(Method onMsg, JakartaWebSocketFrameHandlerMetadat
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 @@ private boolean matchDecoders(Method onMsg, JakartaWebSocketFrameHandlerMetadata
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 @@ private void assertSignatureValid(Class> endpointClass, Method method, Class
* 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 static MethodHandle bindTemplateVariables(MethodHandle target, String[] n
final int IDX = 1;
- MethodHandle retHandle = target;
+ MethodHolder retHandle = target;
if ((templateValues == null) || (templateValues.isEmpty()))
{
@@ -527,54 +524,54 @@ public static MethodHandle bindTemplateVariables(MethodHandle target, String[] n
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 a5587ae30ae4..7511f372e8cb 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 static JakartaWebSocketMessageMetadata copyOf(JakartaWebSocketMessageMeta
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 void setMaxMessageSize(int maxMessageSize)
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 a62d243fb891..b952888ac8fa 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
@@ -25,6 +25,7 @@
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 +33,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 +59,7 @@ void invoke(Object message)
{
try
{
- _methodHandle.invoke(message);
+ _methodHolder.invoke(message);
}
catch (Throwable t)
{
@@ -67,7 +68,7 @@ void invoke(Object message)
}
/**
- * @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 +91,9 @@ public abstract static class Basic extends AbstractDecodedMes
{
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 +106,9 @@ public abstract static class Stream extends AbstractDecodedMe
{
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 d3715baf8940..28b7b8c1924f 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 6e7b34c3ce0a..f58d2cfc5f01 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
@@ -17,6 +17,7 @@
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;
@@ -28,21 +29,27 @@
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 6b9f98b6b134..a6db6771b77b 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 59bed6e8b854..5fbb7252b807 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
@@ -17,6 +17,7 @@
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;
@@ -28,21 +29,27 @@
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 4e21e76d317d..a927fd560f23 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.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 void testCalendar1Frame() throws Exception
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 void testCalendar3Frames() throws Exception
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 19f2d82c00c3..db830c3d2a19 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.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 void testCalendar1Frame() throws Exception
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 void testCalendar3Frames() throws Exception
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 e3fccf35041a..eac4ee36f05d 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.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 void testDate1Frame() throws Exception
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 void testDate3Frames() throws Exception
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 fe83857050ca..9647c6068864 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.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 void testDate1Frame() throws Exception
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 void testDate3Frames() throws Exception
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 b91f0e28702e..3e08f41e03fc 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.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 void testInputStream1Message1Frame() throws InterruptedException, Executi
{
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 void testInputStream2Messages2Frames() throws InterruptedException, Execu
{
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 void testInputStream1Message3Frames() throws InterruptedException, Execut
{
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 void testInputStream1Message4FramesEmptyFin() throws InterruptedException
{
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 af3264e8d91d..5cc83ebc99cf 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.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 void testReader1Frame() throws InterruptedException, ExecutionException,
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 void testReader3Frames() throws InterruptedException, ExecutionException,
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 578a5ae83e6b..6fd32c011a72 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 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 String onColorMessage(Session session, String message, @Name("color") Str
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 void testOnlyParamString() throws Throwable
// 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 void testOnlyParamInt() throws Throwable
};
// 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 void testLabeledParamStringInt() throws Throwable
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 73b8f3f32446..3e3f83780fbe 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.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 void testQuotesDecodedReaderMessageSink() throws Exception
});
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-servlet/src/test/java/org/eclipse/jetty/ee9/servlet/DefaultServletTest.java b/jetty-ee9/jetty-ee9-servlet/src/test/java/org/eclipse/jetty/ee9/servlet/DefaultServletTest.java
index 880e1dfd0f1d..7dad850157bc 100644
--- a/jetty-ee9/jetty-ee9-servlet/src/test/java/org/eclipse/jetty/ee9/servlet/DefaultServletTest.java
+++ b/jetty-ee9/jetty-ee9-servlet/src/test/java/org/eclipse/jetty/ee9/servlet/DefaultServletTest.java
@@ -1892,6 +1892,7 @@ public void testGzip() throws Exception
rawResponse = connector.getResponse("GET /context/data0.txt HTTP/1.0\r\nHost:localhost:8080\r\n\r\n");
response = HttpTester.parseResponse(rawResponse);
+ System.err.println(response);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
assertThat(response, containsHeaderValue(HttpHeader.CONTENT_LENGTH, "12"));
assertThat(response, containsHeaderValue(HttpHeader.CONTENT_TYPE, "text/plain"));
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 000000000000..76ecd0effa97
--- /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 000000000000..73c0ce3ca132
--- /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 77fbcabffb6f..edcc4aa61fcc 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.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 void onOpen(CoreSession coreSession, Callback callback)
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 void onOpen(CoreSession coreSession, Callback callback)
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 JakartaWebSocketMessageMetadata getTextMetadata()
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))
+ {
+ basicType = OpCode.BINARY;
+ metadata.setSinkClass(PartialByteArrayMessageSink.class);
+ }
+ else if (ByteBuffer.class.isAssignableFrom(clazz))
{
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(MessageHandler.Partial.class, "onMessage", MethodType.methodType(void.class, Object.class, boolean.class))
- .bindTo(handler);
-
- 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);
+ basicType = OpCode.BINARY;
+ metadata.setSinkClass(PartialByteBufferMessageSink.class);
}
- catch (NoSuchMethodException e)
+ else if (String.class.isAssignableFrom(clazz))
{
- throw new IllegalStateException("Unable to find method", e);
+ basicType = OpCode.TEXT;
+ metadata.setSinkClass(PartialStringMessageSink.class);
}
- catch (IllegalAccessException e)
+ else
{
- throw new IllegalStateException("Unable to access " + handler.getClass().getName(), e);
+ 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);
}
public void addMessageHandler(Class clazz, MessageHandler.Whole handler)
{
- try
- {
- MethodHandle methodHandle = JakartaWebSocketFrameHandlerFactory.getServerMethodHandleLookup()
- .findVirtual(MessageHandler.Whole.class, "onMessage", MethodType.methodType(void.class, Object.class))
- .bindTo(handler);
+ MethodHolder methodHolder = new JakartaMessageWholeMethodHolder<>(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);
+ if (PongMessage.class.isAssignableFrom(clazz))
+ {
+ assertBasicTypeNotRegistered(OpCode.PONG, handler);
+ this.pongHandle = methodHolder;
+ registerMessageHandler(OpCode.PONG, clazz, handler, null);
+ return;
+ }
- // 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");
- }
+ AvailableDecoders availableDecoders = session.getDecoders();
+ RegisteredDecoder registeredDecoder = availableDecoders.getFirstRegisteredDecoder(clazz);
+ if (registeredDecoder == null)
+ throw new IllegalStateException("Unable to find Decoder for type: " + clazz);
- // Register the Metadata as a MessageHandler.
- registerMessageHandler(clazz, handler, basicType, metadata);
+ // Create the message metadata specific to the MessageHandler type.
+ JakartaWebSocketMessageMetadata metadata = new JakartaWebSocketMessageMetadata();
+ metadata.setMethodHolder(methodHolder);
+ 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);
}
- catch (NoSuchMethodException e)
+ else if (registeredDecoder.implementsInterface(Decoder.Text.class))
{
- throw new IllegalStateException("Unable to find method", e);
+ basicType = OpCode.TEXT;
+ metadata.setRegisteredDecoders(availableDecoders.getTextDecoders(clazz));
+ metadata.setSinkClass(DecodedTextMessageSink.class);
}
- catch (IllegalAccessException e)
+ else if (registeredDecoder.implementsInterface(Decoder.TextStream.class))
{
- throw new IllegalStateException("Unable to access " + handler.getClass().getName(), e);
+ 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 80e1158f2abd..11022f83bd24 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.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 JakartaWebSocketFrameHandler newJakartaWebSocketFrameHandler(Object endpo
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 JakartaWebSocketFrameHandler newJakartaWebSocketFrameHandler(Object endpo
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 static MessageSink createMessageSink(JakartaWebSocketSession session, Jak
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 static MessageSink createMessageSink(JakartaWebSocketSession session, Jak
}
}
- 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 @@ private MethodHandle toMethodHandle(MethodHandles.Lookup lookup, Method method)
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 @@ private boolean matchOnMessage(Method onMsg, JakartaWebSocketFrameHandlerMetadat
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 @@ private boolean matchOnMessage(Method onMsg, JakartaWebSocketFrameHandlerMetadat
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 @@ private boolean matchOnMessage(Method onMsg, JakartaWebSocketFrameHandlerMetadat
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 @@ private boolean matchDecoders(Method onMsg, JakartaWebSocketFrameHandlerMetadata
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 @@ private void assertSignatureValid(Class> endpointClass, Method method, Class
* 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 static MethodHandle bindTemplateVariables(MethodHandle target, String[] n
final int IDX = 1;
- MethodHandle retHandle = target;
+ MethodHolder retHandle = target;
if ((templateValues == null) || (templateValues.isEmpty()))
{
@@ -527,54 +509,54 @@ public static MethodHandle bindTemplateVariables(MethodHandle target, String[] n
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 891c56e22c0c..480ec3e89aa5 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 static JakartaWebSocketMessageMetadata copyOf(JakartaWebSocketMessageMeta
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 void setMaxMessageSize(int maxMessageSize)
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 94afefa5b982..194b08a9499e 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.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 @@ void invoke(Object message)
{
try
{
- _methodHandle.invoke(message);
+ _methodHolder.invoke(message);
}
catch (Throwable t)
{
@@ -67,7 +67,7 @@ void invoke(Object message)
}
/**
- * @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 static class Basic extends AbstractDecodedMes
{
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 static class Stream extends AbstractDecodedMe
{
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 1eab5c76a87b..f08d165711ac 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,8 +13,7 @@
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;
@@ -27,6 +26,7 @@
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 +34,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 d7d07ad4859f..3d9e41af5d8c 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 @@
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 e7091d4596ef..11cc2179a81a 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,8 +13,7 @@
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;
@@ -26,6 +25,7 @@
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 +33,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 47993416cf15..1bd6fb540557 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,8 +15,7 @@
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;
@@ -28,21 +27,27 @@
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 e9b3cf0b1865..dc245da8720b 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 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 @@ else if (Decoder.BinaryStream.class.isAssignableFrom(clazz))
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 MethodHandle getAcceptHandle(Consumer copy, Class type)
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 aaa05b69ccdc..fd9fc87b60d5 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
@@ -31,6 +31,7 @@
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 +46,7 @@ public void testCalendar1Frame() throws Exception
{
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 +68,7 @@ public void testCalendar3Frames() throws Exception
{
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 47863ff32713..1a28c22ab53b 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
@@ -33,6 +33,7 @@
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 void testCalendar1Frame() throws Exception
{
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 +70,7 @@ public void testCalendar3Frames() throws Exception
{
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 f4c08ab3172e..1d27c4eae7eb 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
@@ -31,6 +31,7 @@
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 +46,7 @@ public void testDate1Frame() throws Exception
{
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 +63,7 @@ public void testDate3Frames() throws Exception
{
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 4dd8cd533ee6..a72fa7cbde46 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
@@ -34,6 +34,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.util.MethodHolder;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -48,7 +49,7 @@ public void testDate1Frame() throws Exception
{
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 +66,7 @@ public void testDate3Frames() throws Exception
{
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 56ccec6089ac..cab219df5341 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
@@ -33,6 +33,7 @@
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
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 +64,7 @@ public void testInputStream1Message1Frame() throws InterruptedException, Executi
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 +92,7 @@ public void testInputStream2Messages2Frames() throws InterruptedException, Execu
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 +114,7 @@ public void testInputStream1Message3Frames() throws InterruptedException, Execut
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 795422ecc4f3..be2910d3474f 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
@@ -28,6 +28,7 @@
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 +41,7 @@ public void testReader1Frame() throws InterruptedException, ExecutionException,
{
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 +57,7 @@ public void testReader3Frames() throws InterruptedException, ExecutionException,
{
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 8d8e43732858..fc2525e5d413 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 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 String onColorMessage(Session session, String message, @Name("color") Str
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 void testOnlyParamString() throws Throwable
// 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 void testOnlyParamInt() throws Throwable
};
// 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 void testLabeledParamStringInt() throws Throwable
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 eec22ab2f5b1..2d666bbae694 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.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 void testQuotesDecodedReaderMessageSink() throws Exception
});
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 6ef8af298cca..c8d5f0d7c96a 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.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 @@ private enum SuspendState
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 @@ private enum SuspendState
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 void onOpen(CoreSession coreSession, Callback callback)
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 51040f628a6d..1b7cb920c856 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.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.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 JettyWebSocketFrameHandler newJettyFrameHandler(Object endpointInstance)
{
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 JettyWebSocketFrameHandler newJettyFrameHandler(Object endpointInstance)
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 static MessageSink createMessageSink(MethodHandle msgHandle, Class exte
{
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 be891e1cb72d..981b10560fa8 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.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 void sendFrame(Frame frame, Callback callback, boolean batch)
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 void sendFrame(Frame frame, Callback callback, boolean batch)
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 92f1c06393f2..d95f6e38dd83 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 000000000000..c531fd4ed48c
--- /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(5)
+ .measurementIterations(10)
+ .forks(1)
+ .threads(1)
+ .build();
+
+ new Runner(opt).run();
+ }
+}
+
+