Skip to content

Commit

Permalink
WebSocket Next: method arguments injection
Browse files Browse the repository at this point in the history
- resolves #39224
  • Loading branch information
mkouba committed Mar 22, 2024
1 parent 26dd881 commit 6ae30e2
Show file tree
Hide file tree
Showing 12 changed files with 533 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
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 parameterContext
* @return {@code true} if this provider matches the given parameter context, {@code false} otherwise
*/
boolean matches(ParameterContext parameterContext);

/**
*
* @param parameterContext
* @param callbackContext
* @return the result handle to be passed as an argument to a callback method
*/
ResultHandle get(ParameterContext parameterContext, CallbackContext callbackContext);

static final int DEFAULT_PRIORITY = 0;

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

interface ParameterContext {

/**
*
* @return the callback
*/
Callback callback();

/**
*
* @return the Java method parameter
*/
MethodParameterInfo parameter();

/**
*
* @return the set of annotations, potentially transformed
*/
Set<AnnotationInstance> paramAnnotations();

}

interface CallbackContext {

/**
*
* @return the bytecode
*/
BytecodeCreator bytecode();

/**
* Obtains the message directly in the bytecode.
*
* @return the message object or {@code null} for {@link OnOpen} and {@link OnClose} callbacks
*/
ResultHandle message();

/**
* Attempts to decode the message directly in the bytecode.
*
* @param parameterType
* @return the decoded message object or {@code null} for {@link OnOpen} and {@link OnClose} callbacks
*/
ResultHandle decodeMessage(Type parameterType);

/**
* Obtains the current connection directly in the bytecode.
*
* @return the current {@link WebSocketConnection}, never {@code null}
*/
ResultHandle connection();

}

}
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,46 @@
package io.quarkus.websockets.next.deployment;

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

import io.quarkus.builder.item.SimpleBuildItem;
import io.quarkus.websockets.next.deployment.ArgumentProvider.ParameterContext;

final class ArgumentProvidersBuildItem extends SimpleBuildItem {

final List<ArgumentProvider> sortedProviders;

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

/**
*
* @param context
* @return the first matching provider or {@code null}
*/
ArgumentProvider findMatching(ParameterContext context) {
for (ArgumentProvider provider : sortedProviders) {
if (provider.matches(context)) {
return provider;
}
}
return null;
}

/**
*
* @param context
* @return all matching providers, never {@code null}
*/
List<ArgumentProvider> findAllMatching(ParameterContext context) {
List<ArgumentProvider> matching = new ArrayList<>();
for (ArgumentProvider provider : sortedProviders) {
if (provider.matches(context)) {
matching.add(provider);
}
}
return matching;
}

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

import io.quarkus.gizmo.ResultHandle;

class ConnectionArgumentProvider implements ArgumentProvider {

@Override
public boolean matches(ParameterContext parameterContext) {
return parameterContext.parameter().type().name().equals(WebSocketDotNames.WEB_SOCKET_CONNECTION);
}

@Override
public ResultHandle get(ParameterContext parameterContext, CallbackContext callbackContext) {
return callbackContext.connection();
}

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

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

import io.quarkus.gizmo.ResultHandle;

class MessageArgumentProvider implements ArgumentProvider {

@Override
public boolean matches(ParameterContext parameterContext) {
return parameterContext.callback().acceptsMessage() && parameterContext.paramAnnotations().isEmpty();
}

@Override
public ResultHandle get(ParameterContext parameterContext, CallbackContext callbackContext) {
return callbackContext.decodeMessage(parameterContext.parameter().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 6ae30e2

Please sign in to comment.