All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.mangoo.routing.handlers.DispatcherHandler Maven / Gradle / Ivy

The newest version!
package io.mangoo.routing.handlers;

import io.mangoo.annotations.FilterWith;
import io.mangoo.constants.NotNull;
import io.mangoo.core.Application;
import io.mangoo.i18n.Messages;
import io.mangoo.interfaces.filters.OncePerRequestFilter;
import io.mangoo.routing.Attachment;
import io.mangoo.templating.TemplateEngine;
import io.mangoo.utils.RequestUtils;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;

public class DispatcherHandler implements HttpHandler {
    private static final Logger LOG = LogManager.getLogger(DispatcherHandler.class);
    private Method method;
    private List methodAnnotations = new ArrayList<>();
    private List classAnnotations = new ArrayList<>();
    private TemplateEngine templateEngine;
    private Messages messages;
    private Map> methodParameters;
    private Class controllerClass;
    private String controllerClassName;
    private String controllerMethodName;
    private String username;
    private String password;
    private int limit;
    private int methodParametersCount;
    private boolean requestFilter;
    private boolean blocking;
    private boolean authentication;

    public DispatcherHandler dispatch(Class controllerClass, String controllerMethodName) {
        Objects.requireNonNull(controllerClass, NotNull.CONTROLLER_CLASS);
        Objects.requireNonNull(controllerMethodName, NotNull.CONTROLLER_METHOD);

        this.templateEngine = Application.getInstance(TemplateEngine.class);
        this.messages = Application.getInstance(Messages.class);
        this.controllerClass = controllerClass;
        this.controllerMethodName = controllerMethodName;
        this.controllerClassName = controllerClass.getSimpleName();
        this.methodParameters = getMethodParameters();
        this.methodParametersCount = this.methodParameters.size();
        this.requestFilter = Application.getInjector().getAllBindings().containsKey(com.google.inject.Key.get(OncePerRequestFilter.class));

        try {
            this.method = Application.getInstance(this.controllerClass)
                    .getClass()
                    .getDeclaredMethod(this.controllerMethodName, this.methodParameters.values().toArray(new Class[0]));
            
            for (Annotation annotation : this.method.getAnnotations()) {
                if (annotation.annotationType().equals(FilterWith.class)) {
                    this.methodAnnotations.add(annotation);
                }
            }
        } catch (NoSuchMethodException | SecurityException e) {
            LOG.error("Failed to create DispatcherHandler", e);
        }
        
        for (Annotation annotation : controllerClass.getAnnotations()) {
            if (annotation.annotationType().equals(FilterWith.class)) {
                this.classAnnotations.add(annotation);
            }
        }
        
        return this;
    }
    
    public DispatcherHandler isBlocking(boolean blocking) {
        this.blocking = blocking;
        return this;
    }
    
    public DispatcherHandler withBasicAuthentication(String username, String password) {
        this.username = username;
        this.password = password;
        
        return this;
    }

    public DispatcherHandler withAuthentication(boolean authentication) {
        this.authentication = authentication;
        return this;
    }

    public DispatcherHandler withLimit(int limit) {
        this.limit = limit;
        return this;
    }
    
    @Override
    public void handleRequest(HttpServerExchange exchange) throws Exception {
        if ( (RequestUtils.isPostPutPatch(exchange) || this.blocking) && exchange.isInIoThread()) {
            exchange.dispatch(this);
            return;
        }

        final var attachment = Attachment.build()
            .withControllerInstance(Application.getInstance(this.controllerClass))
            .withControllerClass(this.controllerClass)
            .withControllerClassName(this.controllerClassName)
            .withControllerMethodName(this.controllerMethodName)
            .withClassAnnotations(this.classAnnotations)
            .withMethodAnnotations(this.methodAnnotations)
            .withMethodParameters(this.methodParameters)
            .withMethod(this.method)
            .withMethodParameterCount(this.methodParametersCount)
            .withRequestFilter(this.requestFilter)
            .withRequestParameter(RequestUtils.getRequestParameters(exchange))
            .withMessages(this.messages)
            .withLimit(this.limit)
            .withAuthentication(this.authentication)
            .withBasicAuthentication(this.username, this.password)
            .withTemplateEngine(this.templateEngine);

        exchange.putAttachment(RequestUtils.getAttachmentKey(), attachment);
        nextHandler(exchange);
    }

    /**
     * Converts the method parameter of a mapped controller method to a map
     *
     * @return A Map containing the declared methods of the method parameters and their class type
     */
    private Map> getMethodParameters() {
        final Map> parameters = new LinkedHashMap<>();
        for (final Method declaredMethod : this.controllerClass.getDeclaredMethods()) {
            if (declaredMethod.getName().equals(this.controllerMethodName) && declaredMethod.getParameterCount() > 0) {
                Arrays.stream(declaredMethod.getParameters()).forEach(parameter -> parameters.put(parameter.getName(), parameter.getType()));
                break;
            }
        }

        return parameters;
    }

    /**
     * Handles the next request in the handler chain
     *
     * @param exchange The HttpServerExchange
     * @throws Exception Thrown when an exception occurs
     */
    private void nextHandler(HttpServerExchange exchange) throws Exception {
        if (StringUtils.isNotBlank(this.username) && StringUtils.isNotBlank(this.password)) {
            var httpHandler = RequestUtils.wrapBasicAuthentication(
                    Application.getInstance(LocaleHandler.class),
                    this.username,
                    this.password);
            
            httpHandler.handleRequest(exchange);
        } else {
            Application.getInstance(LocaleHandler.class).handleRequest(exchange);    
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy