From 29fec79e948c18493887a627255bd830bd84ec5a Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Mon, 20 Sep 2021 02:11:46 +0200 Subject: Refactor ServerLauncher --- .../viatra/solver/language/web/ServerLauncher.java | 134 ++++++++++++++------- 1 file changed, 90 insertions(+), 44 deletions(-) (limited to 'language-web/src/main') diff --git a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java index 63088511..d92c7735 100644 --- a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java +++ b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java @@ -8,26 +8,62 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; +import java.util.Set; + +import javax.servlet.SessionTrackingMode; import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.session.SessionHandler; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.log.Slf4jLog; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.webapp.WebAppContext; public class ServerLauncher { + public static final String DEFAULT_LISTEN_ADDRESS = "localhost"; + + public static final int DEFAULT_LISTEN_PORT = 1312; + + // Use this cookie name for load balancing. + public static final String SESSION_COOKIE_NAME = "JSESSIONID"; + private static final Slf4jLog LOG = new Slf4jLog(ServerLauncher.class.getName()); private final Server server; public ServerLauncher(InetSocketAddress bindAddress, Resource baseResource) { server = new Server(bindAddress); - var ctx = new WebAppContext(); - ctx.setBaseResource(baseResource); - ctx.setWelcomeFiles(new String[] { "index.html" }); - ctx.setContextPath("/"); - ctx.addServlet(ProblemServlet.class, "/xtext-service/*"); - ctx.setInitParameter("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false"); - server.setHandler(ctx); + var handler = new ServletContextHandler(); + addSessionHandler(handler); + addProblemServlet(handler); + if (baseResource != null) { + handler.setBaseResource(baseResource); + handler.setWelcomeFiles(new String[] { "index.html" }); + addDefaultServlet(handler); + } + server.setHandler(handler); + } + + private void addSessionHandler(ServletContextHandler handler) { + var sessionHandler = new SessionHandler(); + sessionHandler.setSessionTrackingModes(Set.of(SessionTrackingMode.COOKIE)); + sessionHandler.setSessionCookie(SESSION_COOKIE_NAME); + handler.setSessionHandler(sessionHandler); + } + + private void addProblemServlet(ServletContextHandler handler) { + handler.addServlet(ProblemServlet.class, "/xtext-service/*"); + } + + private void addDefaultServlet(ServletContextHandler handler) { + var defaultServletHolder = new ServletHolder(DefaultServlet.class); + var isWindows = System.getProperty("os.name").toLowerCase().contains("win"); + // Avoid file locking on Windows: https://stackoverflow.com/a/4985717 + // See also the related Jetty ticket: + // https://github.com/eclipse/jetty.project/issues/2925 + defaultServletHolder.setInitParameter("useFileMappedBuffer", isWindows ? "false" : "true"); + handler.addServlet(defaultServletHolder, "/"); } public void start() throws Exception { @@ -38,55 +74,65 @@ public class ServerLauncher { if (key != -1) { server.stop(); } else { - LOG.warn( - "Console input is not available. In order to stop the server, you need to cancel process manually."); + LOG.warn("Console input is not available. " + + "In order to stop the server, you need to cancel process manually."); } } - private static InetSocketAddress getBindAddress(String listenAddress, int port) { - if (listenAddress == null) { - return new InetSocketAddress(port); - } - return new InetSocketAddress(listenAddress, port); - } - - private static Resource getBaseResource(String baseResourceOverride) throws IOException, URISyntaxException { - if (baseResourceOverride != null) { - return Resource.newResource(baseResourceOverride); - } - var indexUrlInJar = ServerLauncher.class.getResource("/webapp/index.html"); - if (indexUrlInJar == null) { - var workingPath = new String[] { System.getProperty("user.dir"), "build", "webpack", "development", }; - return Resource.newResource(new File(String.join(File.separator, workingPath))); + public static void main(String[] args) { + try { + var bindAddress = getBindAddress(); + var baseResource = getBaseResource(); + var serverLauncher = new ServerLauncher(bindAddress, baseResource); + serverLauncher.start(); + } catch (Exception exception) { + LOG.warn(exception); + System.exit(1); } - var webRootUri = URI.create(indexUrlInJar.toURI().toASCIIString().replaceFirst("/index.html$", "/")); - return Resource.newResource(webRootUri); } - public static void main(String[] args) { + private static String getListenAddress() { var listenAddress = System.getenv("LISTEN_ADDRESS"); if (listenAddress == null) { - listenAddress = "localhost"; + return DEFAULT_LISTEN_ADDRESS; } - var port = 1312; + return listenAddress; + } + + private static int getListenPort() { var portStr = System.getenv("LISTEN_PORT"); if (portStr != null) { - try { - port = Integer.parseInt(portStr); - } catch (NumberFormatException e) { - LOG.warn(e); - System.exit(1); - } + return Integer.parseInt(portStr); } + return DEFAULT_LISTEN_PORT; + } + + private static InetSocketAddress getBindAddress() { + var listenAddress = getListenAddress(); + var listenPort = getListenPort(); + return new InetSocketAddress(listenAddress, listenPort); + } + + private static Resource getBaseResource() throws IOException, URISyntaxException { var baseResourceOverride = System.getenv("BASE_RESOURCE"); - try { - var bindAddress = getBindAddress(listenAddress, port); - var baseResource = getBaseResource(baseResourceOverride); - var serverLauncher = new ServerLauncher(bindAddress, baseResource); - serverLauncher.start(); - } catch (Exception exception) { - LOG.warn(exception); - System.exit(1); + if (baseResourceOverride != null) { + // If a user override is provided, use it. + return Resource.newResource(baseResourceOverride); + } + var indexUrlInJar = ServerLauncher.class.getResource("/webapp/index.html"); + if (indexUrlInJar != null) { + // If the app is packaged in the jar, serve it. + var webRootUri = URI.create(indexUrlInJar.toURI().toASCIIString().replaceFirst("/index.html$", "/")); + return Resource.newResource(webRootUri); + } + // Look for unpacked production artifacts (convenience for running from IDE). + var unpackedResourcePathComponents = new String[] { System.getProperty("user.dir"), "build", "webpack", + "production" }; + var unpackedResourceDir = new File(String.join(File.separator, unpackedResourcePathComponents)); + if (unpackedResourceDir.isDirectory()) { + return Resource.newResource(unpackedResourceDir); } + // Fall back to just serving a 404. + return null; } } -- cgit v1.2.3-70-g09d2