Package org.robotninjas.barge.jaxrs.ws

Source Code of org.robotninjas.barge.jaxrs.ws.RaftJettyServer

package org.robotninjas.barge.jaxrs.ws;

import com.google.common.base.Throwables;

import com.google.common.collect.Lists;
import com.google.common.io.CharStreams;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

import org.glassfish.jersey.servlet.ServletContainer;

import org.robotninjas.barge.jaxrs.RaftApplication;
import org.robotninjas.barge.jaxrs.RaftServer;
import org.robotninjas.barge.state.RaftProtocolListener;
import org.robotninjas.barge.state.StateTransitionListener;
import org.slf4j.bridge.SLF4JBridgeHandler;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;


/**
* An instance for a Raft server using Jetty's embedded HTTP server.
* <p>
* This server exposes events of the lifecycle of Raft instance through a WebSocket API: Clients can connect to the
* <tt>/events/</tt> URI and get notified in real-time of logged events.
* </p>
*/
public class RaftJettyServer implements RaftServer<RaftJettyServer> {

  private static final String help = "Usage: java -jar barge-http.jar [options] <server index>\n" +
      "Options:\n" +
      " -h                       : Displays this help message\n" +
      " -c <configuration file>  : Use given configuration file for cluster configuration\n" +
      "                            This file is a simple property file with indices as keys and URIs as values, eg. like\n\n" +
      "                              0=http://localhost:1234\n" +
      "                              1=http://localhost:3456\n" +
      "                              2=http://localhost:4567\n\n" +
      "                            Default is './barge.conf'\n" +
      "<server index>            : Index of this server in the cluster configuration\n";

  private final Server server;
  private final RaftApplication raftApplication;
  private final WsEventListener events;

  public static void main(String[] args) throws IOException, URISyntaxException {
    muteJul();

    File clusterConfiguration = new File("barge.conf");
    int index = -1;

    for (int i = 0; i < args.length; i++) {

      switch (args[i]) {

        case "-c":
          clusterConfiguration = new File(args[++i]);

          break;

        case "-h":
          usage();
          System.exit(0);

        default:

          try {
            index = Integer.parseInt(args[i].trim());
          } catch (NumberFormatException e) {
            usage();
            System.exit(1);
          }

          break;
      }
    }

    if (index == -1) {
      usage();
      System.exit(1);
    }

    URI[] uris = readConfiguration(clusterConfiguration);

    RaftJettyServer server = new RaftJettyServer(index, uris, new File("log" + index)).start(uris[index].getPort());

    waitForInput();

    server.stop();

    System.out.println("Bye!");
    System.exit(0);
  }

  private static void waitForInput() throws IOException {
    //noinspection ResultOfMethodCallIgnored
    System.in.read();
  }

  private static void muteJul() {
    java.util.logging.Logger.getLogger("").setLevel(Level.ALL);
    SLF4JBridgeHandler.removeHandlersForRootLogger();
    SLF4JBridgeHandler.install();
  }

  private static URI[] readConfiguration(File clusterConfiguration) throws IOException, URISyntaxException {
    List<URI> uris = Lists.newArrayList();

    int lineNumber = 1;

    for (String line : CharStreams.readLines(new FileReader(clusterConfiguration))) {
      String[] pair = line.split("=");

      if (pair.length != 2)
        throw new IOException("Invalid cluster configuration at line " + lineNumber);

      uris.add(Integer.parseInt(pair[0].trim()), new URI(pair[1].trim()));
    }

    return uris.toArray(new URI[uris.size()]);
  }

  private static void usage() {
    System.out.println(help);
  }

  public RaftJettyServer(int serverIndex, URI[] uris, File logDir) {
    server = new Server();
    events = new WsEventListener();
    raftApplication = new RaftApplication(serverIndex, uris, logDir, Collections.<StateTransitionListener>singleton(events), Collections.<RaftProtocolListener>singleton(events));
  }

  public RaftJettyServer start(int port) {
    ServerConnector connector = new ServerConnector(server);
    connector.setPort(port);
    server.addConnector(connector);

    // Setup the basic application "context" for this application at "/"
    // This is also known as the handler tree (in jetty speak)
    ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
    context.setContextPath("/");
    server.setHandler(context);

    // Add a websocket to a specific path spec
    ServletHolder holderEvents = new ServletHolder("ws-events", new EventServlet(events));
    context.addServlet(holderEvents, "/events/*");

    // Add Raft REST services endpoints
    context.addServlet(new ServletHolder(new ServletContainer(raftApplication.makeResourceConfig())), "/raft/*");

    try {
      events.start();
      server.start();

      return this;
    } catch (Throwable t) {
      throw Throwables.propagate(t);
    }
  }

  public void stop() {

    try {
      raftApplication.stop();
      events.stop();
      server.stop();
    } catch (Exception e) {
      throw Throwables.propagate(e);
    }
  }

  public URI getPort() {
    return server.getURI();
  }

  @Override
  public void clean() {

    try {
      raftApplication.clean();
    } catch (IOException e) {
      throw Throwables.propagate(e);
    }
  }

}
TOP

Related Classes of org.robotninjas.barge.jaxrs.ws.RaftJettyServer

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.