package org.opentripplanner.standalone;
import java.io.IOException;
import java.net.BindException;
import lombok.Setter;
import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.http.server.NetworkListener;
import org.glassfish.grizzly.http.server.StaticHttpHandler;
import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;
import com.sun.jersey.api.container.ContainerFactory;
import com.sun.jersey.api.core.PackagesResourceConfig;
import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.core.spi.component.ioc.IoCComponentProviderFactory;
public class GrizzlyServer {
private static final Logger LOG = LoggerFactory.getLogger(GrizzlyServer.class);
@Setter private int port = 8080;
@Setter private String graphDirectory = "/var/otp/graphs/";
@Setter private String staticContentDirectory = "./opentripplanner-leaflet-client/src/main/webapp/";
@Setter private String defaultRouterId = "";
public void start(String[] args) {
/* CONFIGURE LOGGING */
// Remove existing handlers attached to the j.u.l root logger
SLF4JBridgeHandler.removeHandlersForRootLogger(); // (since SLF4J 1.6.5)
// Bridge j.u.l (used by Jersey) to the SLF4J root logger
SLF4JBridgeHandler.install();
/* CONFIGURE GRIZZLY SERVER */
LOG.info("Starting OTP Grizzly server...");
if (args.length > 2)
port = Integer.parseInt(args[2]);
// Rather than use Jersey's GrizzlyServerFactory we will construct one manually, so we can
// set the number of threads, etc.
HttpServer httpServer = new HttpServer();
NetworkListener networkListener = new NetworkListener("sample-listener", "localhost", port);
ThreadPoolConfig threadPoolConfig = ThreadPoolConfig.defaultConfig()
.setCorePoolSize(1).setMaxPoolSize(Runtime.getRuntime().availableProcessors());
networkListener.getTransport().setWorkerThreadPoolConfig(threadPoolConfig);
httpServer.addListener(networkListener);
ResourceConfig rc = new PackagesResourceConfig("org.opentripplanner");
// DelegatingFilterProxy.class.getName() does not seem to work out of the box.
// Register a custom authentication filter, a filter that removes the /ws/ from OTP
// REST API calls, and a filter that wraps JSON in method calls as needed.
rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS,
new String[] { AuthFilter.class.getName(), RewriteFilter.class.getName() });
rc.getProperties().put(ResourceConfig.PROPERTY_CONTAINER_RESPONSE_FILTERS,
new String[] { JsonpFilter.class.getName() });
// Make a factory that hands Jersey OTP modules to inject
IoCComponentProviderFactory ioc_factory = OTPConfigurator.fromCommandLineArguments(args);
/* ADD A COUPLE OF HANDLERS (~SERVLETS) */
// 1. A Grizzly wrapper around the Jersey WebApplication.
// We cannot set the context path to /opentripplanner-api-webapp/ws
// https://java.net/jira/browse/GRIZZLY-1481?focusedCommentId=360385&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_360385
HttpHandler handler = ContainerFactory.createContainer(HttpHandler.class, rc, ioc_factory);
httpServer.getServerConfiguration().addHttpHandler(handler, "/opentripplanner-api-webapp/");
// 2. A static content server for the client JS apps etc.
// This is a filesystem path, not classpath.
// Files are relative to the project dir, so
// from ./ we can reach e.g. target/classes/data-sources.xml
staticContentDirectory = "../opentripplanner-leaflet-client/src/main/webapp/";
httpServer.getServerConfiguration().addHttpHandler(new StaticHttpHandler(staticContentDirectory), "/");
/* RELINQUISH CONTROL TO THE SERVER THREAD */
try {
httpServer.start();
LOG.info("Grizzly server running.");
Thread.currentThread().join();
} catch (BindException be) {
LOG.error("Cannot bind to port {}. Is it already in use?", port);
} catch (IOException ioe) {
LOG.error("IO exception while starting server.");
} catch (InterruptedException ie) {
httpServer.stop();
}
}
public static void main(String[] args) {
(new GrizzlyServer()).start(args);
}
}