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