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

io.vrap.rmf.base.client.http.HandlerStack Maven / Gradle / Ivy

There is a newer version: 17.17.0
Show newest version

package io.vrap.rmf.base.client.http;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

import io.vrap.rmf.base.client.ApiHttpRequest;
import io.vrap.rmf.base.client.ApiHttpResponse;
import io.vrap.rmf.base.client.AutoCloseableService;
import io.vrap.rmf.base.client.VrapHttpClient;

/**
 * The HandlerStack is used to execute the middlewares in order and transfer the request using the specified {@link HttpHandler}
 */
public class HandlerStack extends AutoCloseableService implements VrapHttpClient {
    public String CLOSED_MESSAGE = "Handler is already closed.";

    private final HttpHandler handler;

    private final List middlewares;

    private Function>> cached;

    private HandlerStack(final HttpHandler handler, final List middlewares) {
        this.handler = handler;
        this.middlewares = middlewares;
        this.cached = null;
    }

    public static HandlerStack create(final HttpHandler handler, final List middlewares) {
        return new HandlerStack(handler, middlewares);
    }

    public static HandlerStack create(final HttpHandler handler) {
        return create(handler, new ArrayList<>());
    }

    public void addMiddleware(final Middleware middleware) {
        this.middlewares.add(middleware);
        this.cached = null;
    }

    public void addMiddlewares(final List middlewares) {
        this.middlewares.addAll(middlewares);
        this.cached = null;
    }

    public void addMiddlewares(final Middleware... middlewares) {
        this.middlewares.addAll(Arrays.asList(middlewares));
        this.cached = null;
    }

    Function>> resolve() {
        if (cached == null) {
            List stack = new ArrayList<>(middlewares);

            Function>> prev = handler::execute;

            for (Middleware middleware : stack) {
                Function>> finalPrev = prev;
                prev = (request) -> middleware.invoke(request, finalPrev);
            }

            cached = prev;
        }

        return cached;
    }

    @Override
    public CompletableFuture> execute(ApiHttpRequest request) {
        rejectExecutionIfClosed(CLOSED_MESSAGE);
        return invoke(request);
    }

    public CompletableFuture> invoke(final ApiHttpRequest request) {
        final Function>> handler = resolve();

        return handler.apply(request);
    }

    @Override
    protected void internalClose() {
        handler.close();
        middlewares.forEach(middleware -> {
            if (middleware instanceof AutoCloseable) {
                closeQuietly((AutoCloseable) middleware);
            }
        });
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy