diff options
Diffstat (limited to 'language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java')
-rw-r--r-- | language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java | 134 |
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; | |||
8 | import java.net.InetSocketAddress; | 8 | import java.net.InetSocketAddress; |
9 | import java.net.URI; | 9 | import java.net.URI; |
10 | import java.net.URISyntaxException; | 10 | import java.net.URISyntaxException; |
11 | import java.util.Set; | ||
12 | |||
13 | import javax.servlet.SessionTrackingMode; | ||
11 | 14 | ||
12 | import org.eclipse.jetty.server.Server; | 15 | import org.eclipse.jetty.server.Server; |
16 | import org.eclipse.jetty.server.session.SessionHandler; | ||
17 | import org.eclipse.jetty.servlet.DefaultServlet; | ||
18 | import org.eclipse.jetty.servlet.ServletContextHandler; | ||
19 | import org.eclipse.jetty.servlet.ServletHolder; | ||
13 | import org.eclipse.jetty.util.log.Slf4jLog; | 20 | import org.eclipse.jetty.util.log.Slf4jLog; |
14 | import org.eclipse.jetty.util.resource.Resource; | 21 | import org.eclipse.jetty.util.resource.Resource; |
15 | import org.eclipse.jetty.webapp.WebAppContext; | ||
16 | 22 | ||
17 | public class ServerLauncher { | 23 | public 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 | } |