Package fitnesse.slim

Source Code of fitnesse.slim.SlimService$Options

// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the CPL Common Public License version 1.0.
package fitnesse.slim;

import fitnesse.slim.fixtureInteraction.DefaultInteraction;
import util.CommandLine;

import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

import fitnesse.socketservice.SocketFactory;

import static fitnesse.slim.JavaSlimFactory.createJavaSlimFactory;

public class SlimService {
  public static final String OPTION_DESCRIPTOR = "[-v] [-i interactionClass] [-s statementTimeout] [-d] port";
  static Class<? extends DefaultInteraction> interactionClass = DefaultInteraction.class;

  public static class Options {
    final boolean verbose;
    final int port;
    final Class<? extends DefaultInteraction> interactionClass;
    /**
     * daemon mode: keep accepting new connections indefinitely.
     */
    final boolean daemon;
    final Integer statementTimeout;

    public Options(boolean verbose, int port, Class<? extends DefaultInteraction> interactionClass, boolean daemon, Integer statementTimeout) {
      this.verbose = verbose;
      this.port = port;
      this.interactionClass = interactionClass;
      this.daemon = daemon;
      this.statementTimeout = statementTimeout;
    }
  }

  private final ServerSocket serverSocket;
  private final SlimServer slimServer;
  private final boolean daemon;
  private final Executor executor = Executors.newFixedThreadPool(5);
  static Thread service;

  public static void main(String[] args) throws IOException {
    Options options = parseCommandLine(args);
    if (options != null) {
      startWithFactory(createJavaSlimFactory(options), options);
    } else {
      parseCommandLineFailed(args);
    }
  }

  protected static void parseCommandLineFailed(String[] args) {
    System.err.println("Invalid command line arguments: " + Arrays.asList(args));
    System.err.println("Usage:");
    System.err.println("    " + SlimService.class.getName() + " " + OPTION_DESCRIPTOR);
  }

  public static void startWithFactory(SlimFactory slimFactory, Options options) throws IOException {
    SlimService slimservice = new SlimService(slimFactory.getSlimServer(options.verbose), options.port, options.interactionClass, options.daemon);
    slimservice.accept();
  }

  // For testing only -- for now
  public static synchronized void startWithFactoryAsync(SlimFactory slimFactory, Options options) throws IOException {
    if (service != null && service.isAlive()) {
      System.err.println("Already an in-process server running: " + service.getName() + " (alive=" + service.isAlive() + ")");
      service.interrupt();
      throw new RuntimeException("Already an in-process server running: " + service.getName() + " (alive=" + service.isAlive() + ")");
    }
    final SlimService slimservice = new SlimService(slimFactory.getSlimServer(options.verbose), options.port, options.interactionClass, options.daemon);
    service = new Thread() {
      public void run() {
        try {
          slimservice.accept();
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      }
    };
    service.start();
  }

  // For testing, mainly.
  public static void waitForServiceToStopAsync() throws InterruptedException {
    // wait for service to close.
    for (int i = 0; i < 1000; i++) {
      if (!service.isAlive())
        break;
      Thread.sleep(50);
    }
  }

  public static Options parseCommandLine(String[] args) {
    CommandLine commandLine = new CommandLine(OPTION_DESCRIPTOR);
    if (commandLine.parse(args)) {
      boolean verbose = commandLine.hasOption("v");
      String interactionClassName = commandLine.getOptionArgument("i", "interactionClass");
      String portString = commandLine.getArgument("port");
      int port = (portString == null) ? 8099 : Integer.parseInt(portString);
      String statementTimeoutString = commandLine.getOptionArgument("s", "statementTimeout");
      Integer statementTimeout = (statementTimeoutString == null) ? null : Integer.parseInt(statementTimeoutString);
      boolean daemon = commandLine.hasOption("d");
      return new Options(verbose, port, getInteractionClass(interactionClassName), daemon, statementTimeout);
    }
    return null;
  }

  public SlimService(SlimServer slimServer, int port, Class<? extends DefaultInteraction> interactionClass, boolean daemon) throws IOException {
    SlimService.interactionClass = interactionClass;
    this.daemon = daemon;
    this.slimServer = slimServer;

    try {
      serverSocket = SocketFactory.tryCreateServerSocket(port);
    } catch (java.lang.OutOfMemoryError e) {
      System.err.println("Out of Memory. Aborting.");
      e.printStackTrace();
      System.exit(99);
      throw e;
    } catch (BindException e) {
      System.err.println("Can not bind to port " + port + ". Aborting.");
      e.printStackTrace();
      throw e;
    }
  }

  public void accept() throws IOException {
    try {
      if (daemon) {
        acceptMany();
      } else {
        acceptOne();
      }
    } catch (java.lang.OutOfMemoryError e) {
      System.err.println("Out of Memory. Aborting");
      e.printStackTrace();
      System.exit(99);
    } finally {
      serverSocket.close();
    }
  }

  private void acceptMany() throws IOException {
    while (true) {
      final Socket socket = serverSocket.accept();
      executor.execute(new Runnable() {

        @Override
        public void run() {
          try {
            handle(socket);
          } catch (IOException e) {
            throw new RuntimeException(e);
          }
        }
      });
    }
  }

  private void handle(Socket socket) throws IOException {
    try {
      slimServer.serve(socket);
    } finally {
      socket.close();
    }
  }

  private void acceptOne() throws IOException {
    Socket socket = serverSocket.accept();
    handle(socket);
  }

  @SuppressWarnings("unchecked")
  private static Class<DefaultInteraction> getInteractionClass(String interactionClassName) {
    if (interactionClassName == null) {
      return DefaultInteraction.class;
    }
    try {
      return (Class<DefaultInteraction>) Class.forName(interactionClassName);
    } catch (ClassNotFoundException e) {
      throw new RuntimeException(e);
    }
  }

  public static Class<? extends DefaultInteraction> getInteractionClass() {
    return interactionClass;
  }
}
TOP

Related Classes of fitnesse.slim.SlimService$Options

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.