package com.github.aesteve.vertx.nubes.reflections.visitors; import com.github.aesteve.vertx.nubes.Config; import com.github.aesteve.vertx.nubes.annotations.sockjs.bridge.EventBusBridge; import com.github.aesteve.vertx.nubes.annotations.sockjs.bridge.InboundPermitted; import com.github.aesteve.vertx.nubes.annotations.sockjs.bridge.OutboundPermitted; import io.vertx.core.Vertx; import io.vertx.core.VertxException; import io.vertx.core.eventbus.EventBus; import io.vertx.core.logging.Logger; import io.vertx.core.logging.LoggerFactory; import io.vertx.ext.web.Router; import io.vertx.ext.web.handler.sockjs.*; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Map; public class EventBusBridgeVisitor<T> extends BaseVisitor<T> { private static final Logger LOG = LoggerFactory.getLogger(EventBusBridgeVisitor.class); private SockJSHandler sockJSHandler; public EventBusBridgeVisitor(Class<T> clazz, Config config, Router router) { super(clazz, config, router); } public void visit() { sockJSHandler = SockJSHandler.create(config.getVertx(), config.getSockJSOptions()); try { instance = clazz.newInstance(); injectServices(); } catch (Exception e) { throw new VertxException("Could not instanciate socket controller : " + clazz.getName(), e); } EventBusBridge annot = clazz.getAnnotation(EventBusBridge.class); path = annot.value(); BridgeOptions bridge = createBridgeOptions(clazz); Map<BridgeEventType, Method> handlers = BridgeEventFactory.createFromController(clazz); sockJSHandler.bridge(bridge, be -> { Method method = handlers.get(be.type()); if (method != null) { tryToInvoke(instance, method, be); } else { be.complete(true); } }); normalizePath(); router.route(path).handler(sockJSHandler); } private static BridgeOptions createBridgeOptions(Class<?> controller) { BridgeOptions options = new BridgeOptions(); InboundPermitted[] inbounds = controller.getAnnotationsByType(InboundPermitted.class); if (inbounds.length > 0) { List<PermittedOptions> inboundPermitteds = new ArrayList<>(inbounds.length); for (InboundPermitted inbound : inbounds) { inboundPermitteds.add(createInboundPermitted(inbound)); } options.setInboundPermitted(inboundPermitteds); } else { options.addInboundPermitted(new PermittedOptions()); } OutboundPermitted[] outbounds = controller.getAnnotationsByType(OutboundPermitted.class); if (outbounds.length > 0) { List<PermittedOptions> outboundPermitteds = new ArrayList<>(outbounds.length); for (OutboundPermitted outbound : outbounds) { outboundPermitteds.add(createOutboundPermitted(outbound)); } options.setOutboundPermitted(outboundPermitteds); } else { options.addOutboundPermitted(new PermittedOptions()); } return options; } private static PermittedOptions createOutboundPermitted(OutboundPermitted outbound) { String address = outbound.address(); String addressRegex = outbound.addressRegex(); String requiredAuthority = outbound.requiredAuthority(); return createPermittedOptions(address, addressRegex, requiredAuthority); } private static PermittedOptions createInboundPermitted(InboundPermitted inbound) { String address = inbound.address(); String addressRegex = inbound.addressRegex(); String requiredAuthority = inbound.requiredAuthority(); return createPermittedOptions(address, addressRegex, requiredAuthority); } private static PermittedOptions createPermittedOptions(String address, String addressRegex, String requiredAuthority) { PermittedOptions options = new PermittedOptions(); if (!"".equals(address)) { options.setAddress(address); } if (!"".equals(addressRegex)) { options.setAddressRegex(addressRegex); } if (!"".equals(requiredAuthority)) { options.setRequiredAuthority(requiredAuthority); } return options; } private void tryToInvoke(Object instance, Method method, BridgeEvent be) { List<Object> paramInstances = new ArrayList<>(); for (Class<?> parameterClass : method.getParameterTypes()) { final Vertx vertx = config.getVertx(); if (parameterClass.equals(BridgeEvent.class)) { paramInstances.add(be); } else if (parameterClass.equals(EventBus.class)) { paramInstances.add(vertx.eventBus()); } else if (parameterClass.equals(Vertx.class)) { paramInstances.add(vertx); } } try { method.invoke(instance, paramInstances.toArray()); } catch (Exception e) { LOG.error("Error while handling websocket", e); if (!be.failed() && !be.succeeded()) { be.fail(e); } } } }