]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.lib.jetty/src/org/argeo/cms/jetty/CmsJettyServer.java
39fc66d9d8218d673317e00534288b627e19b2cc
[lgpl/argeo-commons.git] / org.argeo.cms.lib.jetty / src / org / argeo / cms / jetty / CmsJettyServer.java
1 package org.argeo.cms.jetty;
2
3 import java.nio.file.Files;
4 import java.nio.file.Path;
5
6 import javax.servlet.ServletContext;
7 import javax.servlet.ServletException;
8 import javax.websocket.DeploymentException;
9 import javax.websocket.server.ServerContainer;
10 import javax.websocket.server.ServerEndpointConfig;
11
12 import org.argeo.api.cms.CmsLog;
13 import org.argeo.api.cms.CmsState;
14 import org.argeo.cms.CmsDeployProperty;
15 import org.argeo.cms.websocket.javax.server.CmsWebSocketConfigurator;
16 import org.argeo.cms.websocket.javax.server.TestEndpoint;
17 import org.eclipse.jetty.http.UriCompliance;
18 import org.eclipse.jetty.server.HttpConfiguration;
19 import org.eclipse.jetty.server.HttpConnectionFactory;
20 import org.eclipse.jetty.server.SecureRequestCustomizer;
21 import org.eclipse.jetty.server.Server;
22 import org.eclipse.jetty.server.ServerConnector;
23 import org.eclipse.jetty.server.SslConnectionFactory;
24 import org.eclipse.jetty.server.session.SessionHandler;
25 import org.eclipse.jetty.servlet.ServletContextHandler;
26 import org.eclipse.jetty.util.ssl.SslContextFactory;
27 import org.eclipse.jetty.util.thread.QueuedThreadPool;
28
29 import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer;
30 import org.eclipse.jetty.websocket.javax.server.config.JavaxWebSocketServletContainerInitializer.Configurator;
31
32 public class CmsJettyServer {
33 private static final CmsLog log = CmsLog.getLog(CmsJettyServer.class);
34
35 private static final int DEFAULT_IDLE_TIMEOUT = 30000;
36 private static final String CONTEXT_TEMPDIR = "javax.servlet.context.tempdir";
37
38 // Equinox compatibility
39 private static final String INTERNAL_CONTEXT_CLASSLOADER = "org.eclipse.equinox.http.jetty.internal.ContextClassLoader";
40
41 private Server server;
42 private Path tempDir;
43
44 private ServerConnector httpConnector;
45 private ServerConnector httpsConnector;
46
47 // WebSocket
48 private ServerContainer wsServerContainer;
49 private ServerEndpointConfig.Configurator wsEndpointConfigurator;
50
51 private CmsState cmsState;
52
53 public void start() {
54 try {
55 tempDir = Files.createTempDirectory("jetty");
56
57 server = new Server(new QueuedThreadPool(10, 1));
58
59 configure();
60 // context.addServlet(new ServletHolder(new RWTServlet()), "/" + entryPoint);
61 // Required to serve rwt-resources. It is important that this is last.
62 // ServletHolder holderPwd = new ServletHolder("default", DefaultServlet.class);
63 // context.addServlet(holderPwd, "/");
64
65 if (httpConnector != null) {
66 httpConnector.open();
67 server.addConnector(httpConnector);
68 }
69
70 if (httpsConnector != null) {
71 httpsConnector.open();
72 server.addConnector(httpsConnector);
73 }
74
75 // holder
76
77 // context
78 ServletContextHandler httpContext = createHttpContext();
79 // httpContext.addServlet(holder, "/*");
80 addServlets(httpContext);
81 enableWebSocket(httpContext);
82 server.setHandler(httpContext);
83
84 //
85 // START
86 server.start();
87 //
88
89 Runtime.getRuntime().addShutdownHook(new Thread(() -> stop(), "Jetty shutdown"));
90
91 log.info(httpPortsMsg());
92 } catch (Exception e) {
93 throw new IllegalStateException("Cannot start Jetty HTTPS server", e);
94 }
95 }
96
97 protected void addServlets(ServletContextHandler servletContextHandler) throws ServletException {
98 }
99
100 public Integer getHttpPort() {
101 if (httpConnector == null)
102 return null;
103 return httpConnector.getLocalPort();
104 }
105
106 public Integer getHttpsPort() {
107 if (httpsConnector == null)
108 return null;
109 return httpsConnector.getLocalPort();
110 }
111
112 public void stop() {
113 try {
114 // serverConnector.close();
115 server.stop();
116 // TODO delete temp dir
117 } catch (Exception e) {
118 e.printStackTrace();
119 }
120
121 }
122
123 protected void configure() {
124 HttpConfiguration http_config = new HttpConfiguration();
125
126 String httpPortStr = getFrameworkProp(CmsDeployProperty.HTTP_PORT);
127 String httpsPortStr = getFrameworkProp(CmsDeployProperty.HTTPS_PORT);
128
129 /// TODO make it more generic
130 String httpHost = getFrameworkProp(CmsDeployProperty.HOST);
131 // String httpsHost = getFrameworkProp(
132 // JettyConfig.JETTY_PROPERTY_PREFIX + CmsHttpConstants.HTTPS_HOST);
133
134 // try {
135 if (httpPortStr != null || httpsPortStr != null) {
136 boolean httpEnabled = httpPortStr != null;
137 // props.put(JettyHttpConstants.HTTP_ENABLED, httpEnabled);
138 boolean httpsEnabled = httpsPortStr != null;
139 // props.put(JettyHttpConstants.HTTPS_ENABLED, httpsEnabled);
140 if (httpsEnabled) {
141 int httpsPort = Integer.parseInt(httpsPortStr);
142 http_config.setSecureScheme("https");
143 http_config.setSecurePort(httpsPort);
144 }
145
146 if (httpEnabled) {
147 int httpPort = Integer.parseInt(httpPortStr);
148 httpConnector = new ServerConnector(server, new HttpConnectionFactory(http_config));
149 httpConnector.setPort(httpPort);
150 httpConnector.setHost(httpHost);
151 httpConnector.setIdleTimeout(DEFAULT_IDLE_TIMEOUT);
152 }
153
154 if (httpsEnabled) {
155
156 SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
157 // sslContextFactory.setKeyStore(KeyS)
158
159 sslContextFactory.setKeyStoreType(getFrameworkProp(CmsDeployProperty.SSL_KEYSTORETYPE));
160 sslContextFactory.setKeyStorePath(getFrameworkProp(CmsDeployProperty.SSL_KEYSTORE));
161 sslContextFactory.setKeyStorePassword(getFrameworkProp(CmsDeployProperty.SSL_PASSWORD));
162 // sslContextFactory.setKeyManagerPassword(getFrameworkProp(CmsDeployProperty.SSL_KEYPASSWORD));
163 sslContextFactory.setProtocol("TLS");
164
165 sslContextFactory.setTrustStoreType(getFrameworkProp(CmsDeployProperty.SSL_TRUSTSTORETYPE));
166 sslContextFactory.setTrustStorePath(getFrameworkProp(CmsDeployProperty.SSL_TRUSTSTORE));
167 sslContextFactory.setTrustStorePassword(getFrameworkProp(CmsDeployProperty.SSL_TRUSTSTOREPASSWORD));
168
169 String wantClientAuth = getFrameworkProp(CmsDeployProperty.SSL_WANTCLIENTAUTH);
170 if (wantClientAuth != null && wantClientAuth.equals(Boolean.toString(true)))
171 sslContextFactory.setWantClientAuth(true);
172 String needClientAuth = getFrameworkProp(CmsDeployProperty.SSL_NEEDCLIENTAUTH);
173 if (needClientAuth != null && needClientAuth.equals(Boolean.toString(true)))
174 sslContextFactory.setNeedClientAuth(true);
175
176 // HTTPS Configuration
177 HttpConfiguration https_config = new HttpConfiguration(http_config);
178 https_config.addCustomizer(new SecureRequestCustomizer());
179 https_config.setUriCompliance(UriCompliance.LEGACY);
180
181 // HTTPS connector
182 httpsConnector = new ServerConnector(server, new SslConnectionFactory(sslContextFactory, "http/1.1"),
183 new HttpConnectionFactory(https_config));
184 int httpsPort = Integer.parseInt(httpsPortStr);
185 httpsConnector.setPort(httpsPort);
186 httpsConnector.setHost(httpHost);
187 }
188
189 }
190
191 }
192
193 protected void enableWebSocket(ServletContextHandler servletContextHandler) {
194 String webSocketEnabled = getFrameworkProp(CmsDeployProperty.WEBSOCKET_ENABLED);
195 // web socket
196 if (webSocketEnabled != null && webSocketEnabled.equals(Boolean.toString(true))) {
197 JavaxWebSocketServletContainerInitializer.configure(servletContextHandler, new Configurator() {
198
199 @Override
200 public void accept(ServletContext servletContext, ServerContainer serverContainer)
201 throws DeploymentException {
202 wsServerContainer = serverContainer;
203
204 wsEndpointConfigurator = new CmsWebSocketConfigurator();
205
206 ServerEndpointConfig config = ServerEndpointConfig.Builder
207 .create(TestEndpoint.class, "/ws/test/events/").configurator(wsEndpointConfigurator)
208 .build();
209 try {
210 wsServerContainer.addEndpoint(config);
211 } catch (DeploymentException e) {
212 throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e);
213 }
214 }
215 });
216 }
217 }
218
219 protected ServletContextHandler createHttpContext() {
220 ServletContextHandler httpContext = new ServletContextHandler();
221 httpContext.setAttribute(INTERNAL_CONTEXT_CLASSLOADER, Thread.currentThread().getContextClassLoader());
222 httpContext.setClassLoader(this.getClass().getClassLoader());
223 httpContext.setContextPath("/");
224
225 httpContext.setAttribute(CONTEXT_TEMPDIR, tempDir.toAbsolutePath().toFile());
226 SessionHandler handler = new SessionHandler();
227 handler.setMaxInactiveInterval(-1);
228 httpContext.setSessionHandler(handler);
229
230 return httpContext;
231 }
232
233 private String httpPortsMsg() {
234
235 return (httpConnector != null ? "HTTP " + getHttpPort() + " " : " ")
236 + (httpsConnector != null ? "HTTPS " + getHttpsPort() : "");
237 }
238
239 private String getFrameworkProp(CmsDeployProperty deployProperty) {
240 return cmsState.getDeployProperty(deployProperty.getProperty());
241 }
242
243 public void setCmsState(CmsState cmsState) {
244 this.cmsState = cmsState;
245 }
246
247 }