Package com.elibom.jogger

Source Code of com.elibom.jogger.Jogger

package com.elibom.jogger;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import com.elibom.jogger.exception.NotFoundException;
import com.elibom.jogger.http.Request;
import com.elibom.jogger.http.Response;
import com.elibom.jogger.http.servlet.ServletRequest;
import com.elibom.jogger.http.servlet.ServletResponse;
import com.elibom.jogger.template.FreemarkerTemplateEngine;
import com.elibom.jogger.template.TemplateEngine;
import com.elibom.jogger.util.Preconditions;

/**
* A server that handles HTTP requests using the provided middleware list.
*
* @author German Escobar
*/
public class Jogger {

  private static final int DEFAULT_PORT = 5000;

  /**
   * The Jetty server instance.
   */
  private Server server;

  /**
   * The port in which the server will respond.
   */
  private int port = DEFAULT_PORT;
 
  /**
   * The factory used to create the middleware list.
   */
  private MiddlewaresFactory middlewareFactory;
 
  /**
   * The cached version of the middlewares
   */
  private Middleware[] middlewares;
 
  private TemplateEngine templateEngine = new FreemarkerTemplateEngine();
 
  private ExceptionHandler exceptionHandler = new DefaultExceptionHandler();
 
  /**
   * Constructor. Initializes a new instance without middlewares.
   */
  public Jogger() {
    this(new MiddlewaresFactory() {
      @Override
      public Middleware[] create() {
        return new Middleware[0];
      }
    });
  }
 
  /**
   * Constructor. Initializes a new instance with the supplied middleware list. The order is important because they will be
   * called in that same order.
   *
   * @param middlewares an array of middlewares that will be executed on each request.
   */
  public Jogger(final Middleware...middlewares) {
    Preconditions.notNull(middlewares, "no middlewares provided.");
    this.middlewareFactory = new MiddlewaresFactory() {
      @Override
      public Middleware[] create() {
        return middlewares;
      }
    };
    this.middlewares = middlewares;
  }
 
  /**
   * Constructor. Initializes a new instance with the supplied {@link MiddlewaresFactory}.
   *
   * @param middlewareFactory the factory from which we are going to retrieve the array of middlewares.
   */
  public Jogger(final MiddlewaresFactory middlewareFactory) {
    Preconditions.notNull(middlewareFactory, "no middlewareFactory provided.");
    this.middlewareFactory = middlewareFactory;
    try {
      this.middlewares = middlewareFactory.create();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
 
  /**
   * Handles an HTTP request by delgating the call to the middlewares.
   *
   * @param request the Jogger HTTP request.
   * @param response the Jogger HTTP response.
   * @throws Exception
   */
  public void handle(Request request, Response response) throws Exception {
    if (Environment.isDevelopment()) {
      this.middlewares = this.middlewareFactory.create();
    }
   
    try {
      handle(request, response, new ArrayList<Middleware>(Arrays.asList(middlewares)));
    } catch (Exception e) {
      if (exceptionHandler != null) {
        exceptionHandler.handle(e, request, response);
      } else {
        throw e;
      }
    }
  }
 
  /**
   * Helper method. Creates a {@link MiddlewareChain} implementation to recursively call the middlewares.
   *
   * @param request
   * @param response
   * @param middlewares
   * @throws Exception
   */
  private void handle(final Request request, final Response response, final List<Middleware> middlewares) throws Exception {
    if (middlewares.isEmpty()) {
      throw new NotFoundException();
    }
   
    Middleware current = middlewares.remove(0);
    current.handle(request, response, new MiddlewareChain() {
      @Override
      public void next() throws Exception {
        // recursive call
        handle(request, response, middlewares);
      }
    });
  }

  /**
   * Starts the HTTP server listening in the configured <code>port</code> attribute.
   *
   * @return itself for method chaining.
   */
  public Jogger listen() {
    return listen(port);
  }

  /**
   * Starts the HTTP server listening in the specified <code>port</code>
   *
   * @param port the port in which the HTTP server will listen.
   *
   * @return itself for method chaining.
   */
  public Jogger listen(int port) {
    this.port = port;

    // configure the Jetty server
    server = new Server(port);
    server.setHandler(new JoggerHandler());

    // start the Jetty server
    try {
      server.start();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }

    return this;
  }

  /**
   * Joins to the server thread preventing the program to finish.
   *
   * @return itself for method chaining.
   * @throws InterruptedException if the thread is interrupted.
   */
  public Jogger join() throws InterruptedException {
    server.join();
    return this;
  }

  /**
   * Stops the HTTP server.
   *
   * @return itself for method chaining.
   */
  public Jogger stop() {
    try {
      server.stop();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }

    return this;
  }

  public int getPort() {
    return port;
  }

  public void setPort(int port) {
    this.port = port;
  }

  public Middleware[] getMiddlewareList() {
    return middlewares;
  }

  public TemplateEngine getTemplateEngine() {
    return templateEngine;
  }

  public void setTemplateEngine(TemplateEngine templateEngine) {
    Preconditions.notNull(templateEngine, "no templateEngine provided");
    this.templateEngine = templateEngine;
  }

  public void setExceptionHandler(ExceptionHandler exceptionHandler) {
    this.exceptionHandler = exceptionHandler;
  }

  /**
   * The Jetty handler that will handle HTTP requests.
   *
   * @author German Escobar
   */
  private class JoggerHandler extends AbstractHandler {

    @Override
    public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest servletRequest,
        HttpServletResponse servletResponse) throws IOException, ServletException {
      try {
        // wrap Jetty's request and response in Jogger objects
        Request request = new ServletRequest(servletRequest);
        Response response = new ServletResponse(servletResponse, templateEngine);
       
        Jogger.this.handle(request, response);
      } catch (Exception e) {
        throw new ServletException(e);
      } finally {
        baseRequest.setHandled(true);
      }
    }
  }
}
TOP

Related Classes of com.elibom.jogger.Jogger

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.