Package com.jetdrone.vertx.yoke

Source Code of com.jetdrone.vertx.yoke.WaitForClosure

/**
* Copyright 2011-2014 the original author or authors.
*/
package com.jetdrone.vertx.yoke;

import com.jetdrone.vertx.yoke.core.impl.GroovyRequestWrapper;
import com.jetdrone.vertx.yoke.middleware.YokeRequest;
import com.jetdrone.vertx.yoke.store.SessionStore;
import groovy.lang.Closure;
import org.jetbrains.annotations.NotNull;
import org.vertx.groovy.platform.Container;
import org.vertx.groovy.platform.Verticle;
import org.vertx.java.core.Handler;

import org.vertx.groovy.core.Vertx;
import org.vertx.groovy.core.http.HttpServer;
import org.vertx.java.core.json.JsonObject;

import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
* Yoke is a chain executor of middleware for Vert.x 2.x.
* The goal of this library is not to provide a web application framework but
* the backbone that helps the creation of web applications.
*
* Yoke works in a similar way to Connect middleware. Users start by declaring
* which middleware components want to use and then start an http server either
* managed by Yoke or provided by the user (say when you need https).
*
* Yoke has no extra dependencies than Vert.x itself so it is self contained.
*/
public class GYoke {

    private final Yoke jYoke;
    private final org.vertx.java.core.Vertx vertx;

    /**
     * Creates a Yoke instance.
     *
     * This constructor should be called from a verticle and pass a valid Vertx instance. This instance will be shared
     * with all registered middleware. The reason behind this is to allow middleware to use Vertx features such as file
     * system and timers.
     *
     * <pre>
     * public class MyVerticle extends Verticle {
     *   public void start() {
     *     def yoke = new Yoke(this)
     *     ...
     *   }
     * }
     * </pre>
     * @param verticle the main verticle
     */
    public GYoke(Verticle verticle) {
        this(verticle.getVertx());
    }

    /**
     * Creates a Yoke instance.
     * This constructor should be called from a verticle and pass a valid Vertx
     * instance. This instance will be shared with all registered middleware.
     * The reason behind this is to allow middleware to use Vertx features such
     * as file system and timers.
     *
     * @param vertx The Vertx instance
     */
    public GYoke(Vertx vertx) {
        this.vertx = vertx.toJavaVertx();
        jYoke = new Yoke(this.vertx, new GroovyRequestWrapper());
    }

    public GYoke store(SessionStore store) {
        jYoke.store(store);
        return this;
    }

    /**
     * Adds a Middleware to the chain. If the middleware is an Error Handler Middleware then it is
     * treated differently and only the last error handler is kept.
     *
     * You might want to add a middleware that is only supposed to run on a specific route (path prefix).
     * In this case if the request path does not match the prefix the middleware is skipped automatically.
     *
     * @param route The route prefix for the middleware
     * @param closure The closure add to the chain
     */
    public GYoke use(String route, final Closure closure) {
        final int params = closure.getMaximumNumberOfParameters();
        jYoke.use(route, new Middleware() {
            @Override
            public void handle(@NotNull YokeRequest request, @NotNull Handler<Object> next) {
                if (params == 1) {
                    closure.call(request);
                } else if (params == 2) {
                    closure.call(request, next);
                } else {
                    throw new RuntimeException("Cannot infer the closure signature, should be: request [, next]");
                }
            }
        });
        return this;
    }

    /**
     * Adds a middleware to the chain with the prefix "/".
     * @see Yoke#use(String, Middleware...)
     * @param closure The closure add to the chain
     */
    public GYoke use(Closure closure) {
        return use("/", closure);
    }

    /**
     * Adds a Middleware to the chain. If the middleware is an Error Handler Middleware then it is
     * treated differently and only the last error handler is kept.
     *
     * You might want to add a middleware that is only supposed to run on a specific route (path prefix).
     * In this case if the request path does not match the prefix the middleware is skipped automatically.
     *
     * @param route The route prefix for the middleware
     * @param middleware The middleware add to the chain
     */
    public GYoke use(String route, Middleware... middleware) {
        jYoke.use(route, middleware);
        return this;
    }

    /**
     * Adds a middleware to the chain with the prefix "/".
     * @see Yoke#use(String, Middleware...)
     * @param middleware The middleware add to the chain
     */
    public GYoke use(Middleware... middleware) {
        return use("/", middleware);
    }

    /**
     * Adds a Render Engine to the library. Render Engines are Template engines you
     * might want to use to speed the development of your application. Once they are
     * registered you can use the method render in the YokeResponse to
     * render a template.
     *
     * @param engine The implementation of the engine
     */
    public GYoke engine(String extension, Engine engine) {
        jYoke.engine(extension, engine);
        return this;
    }

    /**
     * When you need to share global properties with your requests you can add them
     * to Yoke and on every request they will be available as request.get(String)
     *
     * @param key unique identifier
     * @param value Any non null value, nulls are not saved
     */
    public void putAt(String key, Object value) {
        jYoke.set(key, value);
    }


    public GYoke keyStoreSecurity(@NotNull final String fileName, @NotNull final String keyStorePassword, @NotNull Map<String, Object> keyPasswords) {
        jYoke.keyStoreSecurity(fileName, keyStorePassword, new JsonObject(keyPasswords));
        return this;
    }

    public GYoke keyStoreSecurity(@NotNull final String fileName, @NotNull final String keyStorePassword) {
        jYoke.keyStoreSecurity(fileName, keyStorePassword);
        return this;
    }

    public GYoke secretSecurity(@NotNull final String secret) {
        jYoke.secretSecurity(secret);
        return this;
    }

    public GYoke secretSecurity(@NotNull final byte[] secret) {
        jYoke.secretSecurity(secret);
        return this;
    }

    public YokeSecurity getSecurity() {
        return jYoke.security();
    }

    /**
     * Starts the server listening at a given port bind to all available interfaces.
     *
     * @param port the server TCP port
     * @return Yoke
     */
    public GYoke listen(int port) {
        return listen(port, "0.0.0.0");
    }

    /**
     * Starts the server listening at a given port and given address.
     *
     * @param port the server TCP port
     * @return Yoke
     */
    public GYoke listen(int port, String address) {
        // create the server
        org.vertx.java.core.http.HttpServer server = vertx.createHttpServer();
        // setup the request handler
        jYoke.listen(server);
        // start listening
        server.listen(port, address);
        return this;
    }

    /**
     * Starts listening at a already created server.
     * @return Yoke
     */
    public GYoke listen(HttpServer gserver) {
        org.vertx.java.core.http.HttpServer server = gserver.toJavaServer();
        jYoke.listen(server);
        return this;
    }

    /** Deploys required middleware
     *
     * @param config configuration to use
     * @param handler Closure tho allow asynchronous result handling
     */
    @SuppressWarnings("unchecked")
    public GYoke deploy(final Container container, final Object config, final Closure handler) {

        if (config == null) {
            if (handler == null) {
                return this;
            } else {
                handler.call((Object) null);
                return this;
            }
        }

        if (config instanceof List) {

            if (((List) config).size() == 0) {
                if (handler == null) {
                    return this;
                } else {
                    handler.call((Object) null);
                    return this;
                }
            }

            final class WaitForClosure extends Closure {
                int latch;
                boolean handled = false;

                WaitForClosure(Object owner, Object thisObject) {
                    super(owner, thisObject);
                    maximumNumberOfParameters = 1;
                    latch = ((List) config).size();
                }

                public Object doCall(org.vertx.groovy.core.AsyncResult argument) {
                    if (handler != null) {
                        latch--;

                        if (!handled && (argument.isFailed() || latch == 0)) {
                            handled = true;
                            handler.call(argument.isFailed() ? argument.getCause() : null);
                        }
                    }
                    return Closure.DONE;
                }

                public Object doCall(org.vertx.java.core.AsyncResult argument) {
                    if (handler != null) {
                        latch--;

                        if (!handled && (argument.failed() || latch == 0)) {
                            handled = true;
                            handler.call(argument.failed() ? argument.cause() : null);
                        }
                    }
                    return Closure.DONE;
                }
            }

            final WaitForClosure waitFor = new WaitForClosure(this, this);

            for (Object o : (List) config) {
                Map mod = (Map) o;

                String module = (String) mod.get("module");
                String verticle = (String) mod.get("verticle");
                Integer instances = (Integer) mod.get("instances");
                Map modConfig = (Map) mod.get("config");
                Boolean worker = (Boolean) mod.get("worker");
                Boolean multiThreaded = (Boolean) mod.get("multiThreaded");

                instances = instances == null ? 1 : instances;
                modConfig = modConfig == null ? Collections.emptyMap() : modConfig;
                worker = worker == null ? false : worker;
                multiThreaded = multiThreaded == null ? false : multiThreaded;

                if (module != null) {
                    deploy(container, module, true, false, false, instances, modConfig, waitFor);
                } else {
                    deploy(container, verticle, false, worker, multiThreaded, instances, modConfig, waitFor);
                }
            }
        } else {
            Map mod = (Map) config;

            String module = (String) mod.get("module");
            String verticle = (String) mod.get("verticle");
            Integer instances = (Integer) mod.get("instances");
            Map modConfig = (Map) mod.get("config");
            Boolean worker = (Boolean) mod.get("worker");
            Boolean multiThreaded = (Boolean) mod.get("multiThreaded");

            instances = instances == null ? 1 : instances;
            modConfig = modConfig == null ? Collections.emptyMap() : modConfig;
            worker = worker == null ? false : worker;
            multiThreaded = multiThreaded == null ? false : multiThreaded;

            if (module != null) {
                deploy(container, module, true, false, false, instances, modConfig, handler);
            } else {
                deploy(container, verticle, false, worker, multiThreaded, instances, modConfig, handler);
            }
        }

        return this;
    }

    private void deploy(Container container, String name, boolean module, boolean worker, boolean multiThreaded, int instances, Map<String, Object> config, Closure handler) {
        if (module) {
            if (handler != null) {
                container.deployModule(name, config, instances, handler);
            } else {
                container.deployModule(name, config, instances);
            }
        } else {
            if (worker) {
                if (handler != null) {
                    container.deployWorkerVerticle(name, config, instances, multiThreaded, handler);
                } else {
                    container.deployWorkerVerticle(name, config, instances, multiThreaded);
                }
            } else {
                if (handler != null) {
                    container.deployVerticle(name, config, instances, handler);
                } else {
                    container.deployVerticle(name, config, instances);
                }
            }
        }
    }

    public Yoke toJavaYoke() {
        return jYoke;
    }
}
TOP

Related Classes of com.jetdrone.vertx.yoke.WaitForClosure

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.