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

net.javapla.jawn.core.Jawn Maven / Gradle / Ivy

The newest version!
package net.javapla.jawn.core;

import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.typesafe.config.Config;

import net.javapla.jawn.core.Plugin.Application;
import net.javapla.jawn.core.Server.ServerConfig;
import net.javapla.jawn.core.internal.Bootstrapper;
import net.javapla.jawn.core.internal.mvc.MvcRouteBuilder;
import net.javapla.jawn.core.internal.reflection.ClassLocator;
import net.javapla.jawn.core.internal.reflection.Reflection;
import net.javapla.jawn.core.util.StringUtil;

public class Jawn {
    
    protected static final Logger log = LoggerFactory.getLogger(Jawn.class);
    static final Logger SYS_ERROR_LOG = LoggerFactory.getLogger("JawnError");
    
    
    private final Bootstrapper booter = new Bootstrapper(); // Core?
    private final LinkedList routes = new LinkedList<>();
    private final LinkedList mvcControllers = new LinkedList<>();
    private final ServerConfig serverConfig = new ServerConfig();
    
    
    
    public Jawn() {
        
    }
    
    /*protected Route.RouteBuilder get(final String path) {
        return _route(HttpMethod.GET, path, (ctx) -> ctx.resp().respond(Status.OK));
    }*/
    protected Route.RouteBuilder get(final String path, final Route.Handler handler) {
        return _route(HttpMethod.GET, path, handler);
    }
    /*protected Route.RouteBuilder get(final String path, final Route.NoResultHandler handler) {
        return _route(HttpMethod.GET, path, handler);
    }*/
    protected Route.RouteBuilder get(final String path, final Route.ZeroArgHandler handler) {
        return _route(HttpMethod.GET, path, handler);
    }
    protected Route.RouteBuilder get(final String path, Object result) {
        return _route(HttpMethod.GET, path, (ctx) -> result).returnType(result.getClass());
    }
    protected Route.RouteBuilder head(final String path, final Route.Handler handler) {
        return _route(HttpMethod.HEAD, path, handler);
    }
    protected Route.RouteBuilder post(final String path, final Route.Handler handler) {
        return _route(HttpMethod.POST, path, handler);
    }
    /*protected Route.RouteBuilder post(final String path, final Route.NoResultHandler handler) {
        return _route(HttpMethod.POST, path, handler);
    }*/
    protected Route.RouteBuilder put(final String path, final Route.Handler handler) {
        return _route(HttpMethod.PUT, path, handler);
    }
    protected Route.RouteBuilder put(final String path, final Route.ZeroArgHandler handler) {
        return _route(HttpMethod.PUT, path, handler);
    }
    protected Route.RouteBuilder delete(final String path, final Route.Handler handler) {
        return _route(HttpMethod.DELETE, path, handler);
    }
    protected Route.RouteBuilder delete(final String path, final Route.ZeroArgHandler handler) {
        return _route(HttpMethod.DELETE, path, handler);
    }
    protected Route.Builder _route(HttpMethod method, final String path, final Route.Handler handler) {
        Route.Builder bob = new Route.Builder(method, _pathPrefix(path), handler);
        routes.add(bob);
        return bob;
    }
    
    protected Jawn routes(Runnable routes) {
        routes.run();
        return this;
    }
    
    /**
     * path("/api/v1/", () -> {
     *   get("/{id}", ctx -> ... );
     *   get("/", ctx -> ... );
     *   post("/", ctx -> ... );
     * });
     * @return
     */
    protected Jawn path(final String rootPath, final Runnable routes) {
        pathPrefix.addLast(rootPath);
        routes(routes);
        pathPrefix.removeLast();
        return this;
    }
    private final LinkedList pathPrefix = new LinkedList<>();
    private String _pathPrefix(String path) {
        return pathPrefix.stream().collect(Collectors.joining("","",path));
    }
    
    
    protected Route.RouteBuilder ws(final String path, WebSocket.Initialiser initialiser) {
        // Only GET is supported to start the handshake
        return _route(HttpMethod.GET, path, new WebSocket.WebSocketHandler(initialiser)).returnType(Context.class);
    }
    
    
/* ******************************************
 * MVC
 * ****************************************** */
    protected Route.RouteBuilder controller(final Class controller) {
        MvcRouteBuilder bob = new MvcRouteBuilder(controller);
        mvcControllers.add(bob);
        return bob;
    }
    protected Route.RouteBuilder controller(Object controller) {
        MvcRouteBuilder bob = new MvcRouteBuilder(controller);
        mvcControllers.add(bob);
        return bob;
    }
    protected void controllers(String packageToScan) {
        ClassLocator.list(packageToScan, booter.classLoader()).forEach(this::controller);
    }
    protected void controllers(Package packageToScan) {
        controllers(packageToScan.getName());
    }
    /**
     * Look for MVC controllers at the standard package by convention.
     * 

* I.e.: The 'controllers' package next to this implementor of {@link Jawn} * *

* This is just a short-hand for controllers(this.getClass().getPackageName() + ".controllers"); */ protected void controllers() { controllers(this.getClass().getPackageName() + ".controllers"); } protected void install(Plugin plugin) { //Server service = loader.findFirst().get(); //registry.register(Server.class, server); // TODO booter.install(plugin); } protected ServerConfig server() { return serverConfig; } /* ****************************************** * Registry * ****************************************** */ protected T require(Class type) { return booter.registry().require(type); } protected void register(Object instance) { booter.registry().register(instance); } /* ****************************************** * Life cycle * ****************************************** */ protected Jawn onStartup(Runnable task) { booter.onStartup(task); return this; } protected Jawn onShutdown(Runnable task) { booter.onShutdown(task); return this; } /** * Running tasks when the server definitely is ready to receive */ protected Jawn onServerStarted(Runnable task) { booter.onServerStarted(task); return this; } public void start() { long startupTime = System.currentTimeMillis(); // shutdown hook Runtime.getRuntime().addShutdownHook(new Thread(this::stop)); // find server ServiceLoader loader = ServiceLoader.load(Server.class); Optional server = loader.findFirst(); if (server.isEmpty()) { throw new IllegalStateException("Server not found"); } // bootstrap //bootstrap.boot(mode, serverConfig, sessionConfig.sessionStore, this::buildRoutes); Application moduleConfig = booter.boot(this::buildRoutes); // TODO ServiceLoader.load Registries after everything else is loaded // start server Config config = booter.config().hasPath("server") ? booter.config().getConfig("server") : null; serverConfig.config(config); try { server.get().start(serverConfig, moduleConfig); } catch (Exception e) { e.printStackTrace(); stop(); return; } // Signal server has started booter.serverStarted(); //log.info(FrameworkBootstrap.FRAMEWORK_SPLASH); log.info("Bootstrap of framework started in: " + (System.currentTimeMillis() - startupTime) + " ms"); //log.info("Jawn: Environment: " + mode.name()); log.info("Jawn: Running on port: " + serverConfig.port()); } public void stop() { booter.shutdown(); } public static final void run(final String ... args) { // TODO // do some command line parsing of the args // port=8080 mode=prod Class caller = Reflection.callingClass(Jawn.class); if (caller == null) { log.error("Could not determine a class extending {}, and therefore not able to start a server", Jawn.class); return; } try { /*Jawn instance = null; if (args.length > 0) { try { instance = caller.getDeclaredConstructor(String[].class).newInstance(args); } catch (NoSuchMethodException nothing) {} } if (instance == null) instance = caller.getDeclaredConstructor().newInstance();*/ Jawn instance = caller.getDeclaredConstructor().newInstance(); instance.start(); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { log.error("", e); } } static Map commandLineParsing(String ... args) { if (args == null || args.length == 0) return Collections.emptyMap(); LinkedHashMap map = new LinkedHashMap<>(); StringUtil.split(args, '=', map::put); return map; } private Stream buildRoutes(Registry registry) { // Execute / instantiate controllers after all other potential classes have been created and are available mvcControllers.forEach(bob -> routes.addAll(bob.build(registry))); return routes.stream(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy