io.micronaut.websocket.context.DefaultWebSocketBeanRegistry Maven / Gradle / Ivy
/*
* Copyright 2017-2020 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.websocket.context;
import io.micronaut.context.BeanContext;
import io.micronaut.context.Qualifier;
import io.micronaut.inject.BeanDefinition;
import io.micronaut.inject.ExecutableMethod;
import io.micronaut.inject.ExecutionHandle;
import io.micronaut.inject.MethodExecutionHandle;
import io.micronaut.inject.qualifiers.Qualifiers;
import io.micronaut.websocket.WebSocketPongMessage;
import io.micronaut.websocket.annotation.OnClose;
import io.micronaut.websocket.annotation.OnError;
import io.micronaut.websocket.annotation.OnMessage;
import io.micronaut.websocket.annotation.OnOpen;
import io.micronaut.websocket.exceptions.WebSocketException;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
/**
* Default implementation of {@link WebSocketBeanRegistry}.
*
* @author graemerocher
* @since 1.0
*/
class DefaultWebSocketBeanRegistry implements WebSocketBeanRegistry {
private final BeanContext beanContext;
private final Class extends Annotation> stereotype;
private final Map, WebSocketBean> webSocketBeanMap = new ConcurrentHashMap<>(3);
/**
* Default constructor.
*
* @param beanContext The bean context
* @param stereotype Stereotype to use for bean lookup
*/
DefaultWebSocketBeanRegistry(BeanContext beanContext, Class extends Annotation> stereotype) {
this.beanContext = beanContext;
this.stereotype = stereotype;
}
@Override
public WebSocketBean getWebSocket(Class type) {
WebSocketBean webSocketBean = webSocketBeanMap.get(type);
if (webSocketBean != null) {
return webSocketBean;
} else {
Qualifier qualifier = Qualifiers.byStereotype(stereotype);
BeanDefinition beanDefinition = beanContext.getBeanDefinition(type, qualifier);
T bean = beanContext.getBean(type, qualifier);
Collection> executableMethods = beanDefinition.getExecutableMethods();
MethodExecutionHandle onOpen = null;
MethodExecutionHandle onClose = null;
MethodExecutionHandle onMessage = null;
MethodExecutionHandle onPong = null;
MethodExecutionHandle onError = null;
for (ExecutableMethod method : executableMethods) {
if (method.isAnnotationPresent(OnOpen.class)) {
onOpen = ExecutionHandle.of(
bean,
method
);
continue;
}
if (method.isAnnotationPresent(OnClose.class)) {
onClose = ExecutionHandle.of(
bean,
method
);
continue;
}
if (method.isAnnotationPresent(OnError.class)) {
onError = ExecutionHandle.of(
bean,
method
);
continue;
}
if (method.isAnnotationPresent(OnMessage.class)) {
if (Arrays.asList(method.getArgumentTypes()).contains(WebSocketPongMessage.class)) {
onPong = ExecutionHandle.of(
bean,
method
);
} else {
onMessage = ExecutionHandle.of(
bean,
method
);
}
}
}
if (onMessage == null) {
throw new WebSocketException("WebSocket handler must specify an @OnMessage handler: " + bean);
}
DefaultWebSocketBean newWebSocketBean = new DefaultWebSocketBean<>(bean, beanDefinition, onOpen, onClose, onMessage, onPong, onError);
if (beanDefinition.isSingleton()) {
webSocketBeanMap.put(type, newWebSocketBean);
}
return newWebSocketBean;
}
}
/**
* Default web socket impl.
*
* @param
* @author graemerocher
*/
private static class DefaultWebSocketBean implements WebSocketBean {
private final T bean;
private final BeanDefinition definition;
private final MethodExecutionHandle onOpen;
private final MethodExecutionHandle onClose;
private final MethodExecutionHandle onMessage;
private final MethodExecutionHandle onPong;
private final MethodExecutionHandle onError;
DefaultWebSocketBean(T bean, BeanDefinition definition, MethodExecutionHandle onOpen, MethodExecutionHandle onClose, MethodExecutionHandle onMessage, MethodExecutionHandle onPong, MethodExecutionHandle onError) {
this.bean = bean;
this.definition = definition;
this.onOpen = onOpen;
this.onClose = onClose;
this.onMessage = onMessage;
this.onPong = onPong;
this.onError = onError;
}
@Override
public BeanDefinition getBeanDefinition() {
return definition;
}
@Override
public T getTarget() {
return bean;
}
@Override
public Optional> messageMethod() {
return Optional.of(onMessage);
}
@Override
public Optional> pongMethod() {
return Optional.ofNullable(onPong);
}
@Override
public Optional> closeMethod() {
return Optional.ofNullable(onClose);
}
@Override
public Optional> openMethod() {
return Optional.ofNullable(onOpen);
}
@Override
public Optional> errorMethod() {
return Optional.ofNullable(onError);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy