aboutsummaryrefslogtreecommitdiffstats
path: root/language-web/src/main
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-09-20 02:11:46 +0200
committerLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-09-20 02:16:23 +0200
commit29fec79e948c18493887a627255bd830bd84ec5a (patch)
tree6688c2a50acb191e5432e2781206dae222b3ca9a /language-web/src/main
parentAllow launching server from Eclipse (diff)
downloadrefinery-29fec79e948c18493887a627255bd830bd84ec5a.tar.gz
refinery-29fec79e948c18493887a627255bd830bd84ec5a.tar.zst
refinery-29fec79e948c18493887a627255bd830bd84ec5a.zip
Refactor ServerLauncher
Diffstat (limited to 'language-web/src/main')
-rw-r--r--language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java134
1 files changed, 90 insertions, 44 deletions
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;
8import java.net.InetSocketAddress; 8import java.net.InetSocketAddress;
9import java.net.URI; 9import java.net.URI;
10import java.net.URISyntaxException; 10import java.net.URISyntaxException;
11import java.util.Set;
12
13import javax.servlet.SessionTrackingMode;
11 14
12import org.eclipse.jetty.server.Server; 15import org.eclipse.jetty.server.Server;
16import org.eclipse.jetty.server.session.SessionHandler;
17import org.eclipse.jetty.servlet.DefaultServlet;
18import org.eclipse.jetty.servlet.ServletContextHandler;
19import org.eclipse.jetty.servlet.ServletHolder;
13import org.eclipse.jetty.util.log.Slf4jLog; 20import org.eclipse.jetty.util.log.Slf4jLog;
14import org.eclipse.jetty.util.resource.Resource; 21import org.eclipse.jetty.util.resource.Resource;
15import org.eclipse.jetty.webapp.WebAppContext;
16 22
17public class ServerLauncher { 23public class ServerLauncher {
24 public static final String DEFAULT_LISTEN_ADDRESS = "localhost";
25
26 public static final int DEFAULT_LISTEN_PORT = 1312;
27
28 // Use this cookie name for load balancing.
29 public static final String SESSION_COOKIE_NAME = "JSESSIONID";
30
18 private static final Slf4jLog LOG = new Slf4jLog(ServerLauncher.class.getName()); 31 private static final Slf4jLog LOG = new Slf4jLog(ServerLauncher.class.getName());
19 32
20 private final Server server; 33 private final Server server;
21 34
22 public ServerLauncher(InetSocketAddress bindAddress, Resource baseResource) { 35 public ServerLauncher(InetSocketAddress bindAddress, Resource baseResource) {
23 server = new Server(bindAddress); 36 server = new Server(bindAddress);
24 var ctx = new WebAppContext(); 37 var handler = new ServletContextHandler();
25 ctx.setBaseResource(baseResource); 38 addSessionHandler(handler);
26 ctx.setWelcomeFiles(new String[] { "index.html" }); 39 addProblemServlet(handler);
27 ctx.setContextPath("/"); 40 if (baseResource != null) {
28 ctx.addServlet(ProblemServlet.class, "/xtext-service/*"); 41 handler.setBaseResource(baseResource);
29 ctx.setInitParameter("org.eclipse.jetty.servlet.Default.useFileMappedBuffer", "false"); 42 handler.setWelcomeFiles(new String[] { "index.html" });
30 server.setHandler(ctx); 43 addDefaultServlet(handler);
44 }
45 server.setHandler(handler);
46 }
47
48 private void addSessionHandler(ServletContextHandler handler) {
49 var sessionHandler = new SessionHandler();
50 sessionHandler.setSessionTrackingModes(Set.of(SessionTrackingMode.COOKIE));
51 sessionHandler.setSessionCookie(SESSION_COOKIE_NAME);
52 handler.setSessionHandler(sessionHandler);
53 }
54
55 private void addProblemServlet(ServletContextHandler handler) {
56 handler.addServlet(ProblemServlet.class, "/xtext-service/*");
57 }
58
59 private void addDefaultServlet(ServletContextHandler handler) {
60 var defaultServletHolder = new ServletHolder(DefaultServlet.class);
61 var isWindows = System.getProperty("os.name").toLowerCase().contains("win");
62 // Avoid file locking on Windows: https://stackoverflow.com/a/4985717
63 // See also the related Jetty ticket:
64 // https://github.com/eclipse/jetty.project/issues/2925
65 defaultServletHolder.setInitParameter("useFileMappedBuffer", isWindows ? "false" : "true");
66 handler.addServlet(defaultServletHolder, "/");
31 } 67 }
32 68
33 public void start() throws Exception { 69 public void start() throws Exception {
@@ -38,55 +74,65 @@ public class ServerLauncher {
38 if (key != -1) { 74 if (key != -1) {
39 server.stop(); 75 server.stop();
40 } else { 76 } else {
41 LOG.warn( 77 LOG.warn("Console input is not available. "
42 "Console input is not available. In order to stop the server, you need to cancel process manually."); 78 + "In order to stop the server, you need to cancel process manually.");
43 } 79 }
44 } 80 }
45 81
46 private static InetSocketAddress getBindAddress(String listenAddress, int port) { 82 public static void main(String[] args) {
47 if (listenAddress == null) { 83 try {
48 return new InetSocketAddress(port); 84 var bindAddress = getBindAddress();
49 } 85 var baseResource = getBaseResource();
50 return new InetSocketAddress(listenAddress, port); 86 var serverLauncher = new ServerLauncher(bindAddress, baseResource);
51 } 87 serverLauncher.start();
52 88 } catch (Exception exception) {
53 private static Resource getBaseResource(String baseResourceOverride) throws IOException, URISyntaxException { 89 LOG.warn(exception);
54 if (baseResourceOverride != null) { 90 System.exit(1);
55 return Resource.newResource(baseResourceOverride);
56 }
57 var indexUrlInJar = ServerLauncher.class.getResource("/webapp/index.html");
58 if (indexUrlInJar == null) {
59 var workingPath = new String[] { System.getProperty("user.dir"), "build", "webpack", "development", };
60 return Resource.newResource(new File(String.join(File.separator, workingPath)));
61 } 91 }
62 var webRootUri = URI.create(indexUrlInJar.toURI().toASCIIString().replaceFirst("/index.html$", "/"));
63 return Resource.newResource(webRootUri);
64 } 92 }
65 93
66 public static void main(String[] args) { 94 private static String getListenAddress() {
67 var listenAddress = System.getenv("LISTEN_ADDRESS"); 95 var listenAddress = System.getenv("LISTEN_ADDRESS");
68 if (listenAddress == null) { 96 if (listenAddress == null) {
69 listenAddress = "localhost"; 97 return DEFAULT_LISTEN_ADDRESS;
70 } 98 }
71 var port = 1312; 99 return listenAddress;
100 }
101
102 private static int getListenPort() {
72 var portStr = System.getenv("LISTEN_PORT"); 103 var portStr = System.getenv("LISTEN_PORT");
73 if (portStr != null) { 104 if (portStr != null) {
74 try { 105 return Integer.parseInt(portStr);
75 port = Integer.parseInt(portStr);
76 } catch (NumberFormatException e) {
77 LOG.warn(e);
78 System.exit(1);
79 }
80 } 106 }
107 return DEFAULT_LISTEN_PORT;
108 }
109
110 private static InetSocketAddress getBindAddress() {
111 var listenAddress = getListenAddress();
112 var listenPort = getListenPort();
113 return new InetSocketAddress(listenAddress, listenPort);
114 }
115
116 private static Resource getBaseResource() throws IOException, URISyntaxException {
81 var baseResourceOverride = System.getenv("BASE_RESOURCE"); 117 var baseResourceOverride = System.getenv("BASE_RESOURCE");
82 try { 118 if (baseResourceOverride != null) {
83 var bindAddress = getBindAddress(listenAddress, port); 119 // If a user override is provided, use it.
84 var baseResource = getBaseResource(baseResourceOverride); 120 return Resource.newResource(baseResourceOverride);
85 var serverLauncher = new ServerLauncher(bindAddress, baseResource); 121 }
86 serverLauncher.start(); 122 var indexUrlInJar = ServerLauncher.class.getResource("/webapp/index.html");
87 } catch (Exception exception) { 123 if (indexUrlInJar != null) {
88 LOG.warn(exception); 124 // If the app is packaged in the jar, serve it.
89 System.exit(1); 125 var webRootUri = URI.create(indexUrlInJar.toURI().toASCIIString().replaceFirst("/index.html$", "/"));
126 return Resource.newResource(webRootUri);
127 }
128 // Look for unpacked production artifacts (convenience for running from IDE).
129 var unpackedResourcePathComponents = new String[] { System.getProperty("user.dir"), "build", "webpack",
130 "production" };
131 var unpackedResourceDir = new File(String.join(File.separator, unpackedResourcePathComponents));
132 if (unpackedResourceDir.isDirectory()) {
133 return Resource.newResource(unpackedResourceDir);
90 } 134 }
135 // Fall back to just serving a 404.
136 return null;
91 } 137 }
92} 138}