Skip to content

Commit

Permalink
WebSocket Next: method arguments injection
Browse files Browse the repository at this point in the history
- resolves quarkusio#39224
  • Loading branch information
mkouba committed Mar 22, 2024
1 parent 26dd881 commit afb64c2
Show file tree
Hide file tree
Showing 12 changed files with 512 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package io.quarkus.websockets.next.deployment;

import java.util.Set;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.MethodParameterInfo;
import org.jboss.jandex.Type;

import io.quarkus.gizmo.BytecodeCreator;
import io.quarkus.gizmo.ResultHandle;
import io.quarkus.websockets.next.OnClose;
import io.quarkus.websockets.next.OnOpen;
import io.quarkus.websockets.next.WebSocketConnection;
import io.quarkus.websockets.next.deployment.WebSocketEndpointBuildItem.Callback;

/**
* Provides arguments for method parameters of a callback method declared on a WebSocket endpoint.
*/
interface ArgumentProvider {

/**
*
* @param callback
* @param parameter The java method parameter
* @param paramAnnotations The set of annotations, potentially transformed
* @return {@code true} if this injector matches the given type and annnotations, {@code false} otherwise
*/
boolean matches(Callback callback, MethodParameterInfo parameter, Set<AnnotationInstance> paramAnnotations);

/**
*
* @param bytecode
* @param parameter
* @param callbackContext
* @return the result handle to be passed as an argument
*/
ResultHandle get(BytecodeCreator bytecode, MethodParameterInfo parameter, CallbackContext callbackContext);

static final int DEFAULT_PRIORITY = 0;

/**
*
* @return the priority
*/
default int priotity() {
return DEFAULT_PRIORITY;
}

/**
*
*/
interface CallbackContext {

Callback callback();

/**
*
* @return the message object or {@code null} for {@link OnOpen} and {@link OnClose} callbacks
*/
ResultHandle getMessage();

/**
*
* @param parameterType
* @return the decoded message object or {@code null} for {@link OnOpen} and {@link OnClose} callbacks
*/
ResultHandle getDecodedMessage(Type parameterType);

/**
*
* @return the current {@link WebSocketConnection}, never {@code null}
*/
ResultHandle getConnection();

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package io.quarkus.websockets.next.deployment;

import io.quarkus.builder.item.MultiBuildItem;

final class ArgumentProviderBuildItem extends MultiBuildItem {

private final ArgumentProvider provider;

ArgumentProviderBuildItem(ArgumentProvider provider) {
this.provider = provider;
}

ArgumentProvider getProvider() {
return provider;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package io.quarkus.websockets.next.deployment;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.MethodParameterInfo;

import io.quarkus.builder.item.SimpleBuildItem;
import io.quarkus.websockets.next.deployment.WebSocketEndpointBuildItem.Callback;

final class ArgumentProvidersBuildItem extends SimpleBuildItem {

final List<ArgumentProvider> sortedProviders;

ArgumentProvidersBuildItem(List<ArgumentProvider> injectors) {
this.sortedProviders = injectors;
}

/**
*
* @param callback
* @param paramType
* @param paramAnnotations
* @param parameterInfo
* @return the first matching provider or {@code null}
*/
ArgumentProvider findMatching(Callback callback, MethodParameterInfo parameterInfo,
Set<AnnotationInstance> paramAnnotations) {
for (ArgumentProvider provider : sortedProviders) {
if (provider.matches(callback, parameterInfo, paramAnnotations)) {
return provider;
}
}
return null;
}

/**
*
* @param callback
* @param paramType
* @param paramAnnotations
* @param parameterInfo
* @return all matching providers, never {@code null}
*/
List<ArgumentProvider> findAllMatching(Callback callback, MethodParameterInfo parameterInfo,
Set<AnnotationInstance> paramAnnotations) {
List<ArgumentProvider> matching = new ArrayList<>();
for (ArgumentProvider provider : sortedProviders) {
if (provider.matches(callback, parameterInfo, paramAnnotations)) {
matching.add(provider);
}
}
return matching;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.quarkus.websockets.next.deployment;

import java.util.Set;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.MethodParameterInfo;

import io.quarkus.gizmo.BytecodeCreator;
import io.quarkus.gizmo.ResultHandle;
import io.quarkus.websockets.next.deployment.WebSocketEndpointBuildItem.Callback;

class ConnectionArgumentProvider implements ArgumentProvider {

@Override
public int priotity() {
return DEFAULT_PRIORITY + 1;
}

@Override
public boolean matches(Callback callback, MethodParameterInfo parameter, Set<AnnotationInstance> paramAnnotations) {
return parameter.type().name().equals(WebSocketDotNames.WEB_SOCKET_CONNECTION);
}

@Override
public ResultHandle get(BytecodeCreator bytecode, MethodParameterInfo parameter, CallbackContext callbackContext) {
return callbackContext.getConnection();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.quarkus.websockets.next.deployment;

import java.util.Set;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.MethodParameterInfo;

import io.quarkus.gizmo.BytecodeCreator;
import io.quarkus.gizmo.ResultHandle;
import io.quarkus.websockets.next.deployment.WebSocketEndpointBuildItem.Callback;

class MessageArgumentProvider implements ArgumentProvider {

@Override
public boolean matches(Callback callback, MethodParameterInfo parameterInfo, Set<AnnotationInstance> paramAnnotations) {
// Match any parameter of @OnTextMessage, @OnBinaryMessage or @OnPongMessage that has no annotations
return callback.acceptsMessage() && paramAnnotations.isEmpty();
}

@Override
public ResultHandle get(BytecodeCreator bytecode, MethodParameterInfo parameterInfo, CallbackContext callbackContext) {
return callbackContext.getDecodedMessage(parameterInfo.type());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ public Callback(AnnotationInstance annotation, MethodInfo method, ExecutionModel
}
}

public boolean isOnOpen() {
return annotation.name().equals(WebSocketDotNames.ON_OPEN);
}

public boolean isOnClose() {
return annotation.name().equals(WebSocketDotNames.ON_CLOSE);
}

public Type returnType() {
return method.returnType();
}
Expand Down
Loading

0 comments on commit afb64c2

Please sign in to comment.