1 package org
.argeo
.cms
.jetty
;
3 import java
.nio
.file
.Files
;
4 import java
.nio
.file
.Path
;
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
;
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
;
29 import org
.eclipse
.jetty
.websocket
.javax
.server
.config
.JavaxWebSocketServletContainerInitializer
;
30 import org
.eclipse
.jetty
.websocket
.javax
.server
.config
.JavaxWebSocketServletContainerInitializer
.Configurator
;
32 public class CmsJettyServer
{
33 private static final CmsLog log
= CmsLog
.getLog(CmsJettyServer
.class);
35 private static final int DEFAULT_IDLE_TIMEOUT
= 30000;
36 private static final String CONTEXT_TEMPDIR
= "javax.servlet.context.tempdir";
38 // Equinox compatibility
39 private static final String INTERNAL_CONTEXT_CLASSLOADER
= "org.eclipse.equinox.http.jetty.internal.ContextClassLoader";
41 private Server server
;
44 private ServerConnector httpConnector
;
45 private ServerConnector httpsConnector
;
48 private ServerContainer wsServerContainer
;
49 private ServerEndpointConfig
.Configurator wsEndpointConfigurator
;
51 private CmsState cmsState
;
55 tempDir
= Files
.createTempDirectory("jetty");
57 server
= new Server(new QueuedThreadPool(10, 1));
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, "/");
65 if (httpConnector
!= null) {
67 server
.addConnector(httpConnector
);
70 if (httpsConnector
!= null) {
71 httpsConnector
.open();
72 server
.addConnector(httpsConnector
);
78 ServletContextHandler httpContext
= createHttpContext();
79 // httpContext.addServlet(holder, "/*");
80 addServlets(httpContext
);
81 enableWebSocket(httpContext
);
82 server
.setHandler(httpContext
);
89 Runtime
.getRuntime().addShutdownHook(new Thread(() -> stop(), "Jetty shutdown"));
91 log
.info(httpPortsMsg());
92 } catch (Exception e
) {
93 throw new IllegalStateException("Cannot start Jetty HTTPS server", e
);
97 protected void addServlets(ServletContextHandler servletContextHandler
) throws ServletException
{
100 public Integer
getHttpPort() {
101 if (httpConnector
== null)
103 return httpConnector
.getLocalPort();
106 public Integer
getHttpsPort() {
107 if (httpsConnector
== null)
109 return httpsConnector
.getLocalPort();
114 // serverConnector.close();
116 // TODO delete temp dir
117 } catch (Exception e
) {
123 protected void configure() {
124 HttpConfiguration http_config
= new HttpConfiguration();
126 String httpPortStr
= getFrameworkProp(CmsDeployProperty
.HTTP_PORT
);
127 String httpsPortStr
= getFrameworkProp(CmsDeployProperty
.HTTPS_PORT
);
129 /// TODO make it more generic
130 String httpHost
= getFrameworkProp(CmsDeployProperty
.HOST
);
131 // String httpsHost = getFrameworkProp(
132 // JettyConfig.JETTY_PROPERTY_PREFIX + CmsHttpConstants.HTTPS_HOST);
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);
141 int httpsPort
= Integer
.parseInt(httpsPortStr
);
142 http_config
.setSecureScheme("https");
143 http_config
.setSecurePort(httpsPort
);
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
);
156 SslContextFactory
.Server sslContextFactory
= new SslContextFactory
.Server();
157 // sslContextFactory.setKeyStore(KeyS)
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");
165 sslContextFactory
.setTrustStoreType(getFrameworkProp(CmsDeployProperty
.SSL_TRUSTSTORETYPE
));
166 sslContextFactory
.setTrustStorePath(getFrameworkProp(CmsDeployProperty
.SSL_TRUSTSTORE
));
167 sslContextFactory
.setTrustStorePassword(getFrameworkProp(CmsDeployProperty
.SSL_TRUSTSTOREPASSWORD
));
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);
176 // HTTPS Configuration
177 HttpConfiguration https_config
= new HttpConfiguration(http_config
);
178 https_config
.addCustomizer(new SecureRequestCustomizer());
179 https_config
.setUriCompliance(UriCompliance
.LEGACY
);
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
);
193 protected void enableWebSocket(ServletContextHandler servletContextHandler
) {
194 String webSocketEnabled
= getFrameworkProp(CmsDeployProperty
.WEBSOCKET_ENABLED
);
196 if (webSocketEnabled
!= null && webSocketEnabled
.equals(Boolean
.toString(true))) {
197 JavaxWebSocketServletContainerInitializer
.configure(servletContextHandler
, new Configurator() {
200 public void accept(ServletContext servletContext
, ServerContainer serverContainer
)
201 throws DeploymentException
{
202 wsServerContainer
= serverContainer
;
204 wsEndpointConfigurator
= new CmsWebSocketConfigurator();
206 ServerEndpointConfig config
= ServerEndpointConfig
.Builder
207 .create(TestEndpoint
.class, "/ws/test/events/").configurator(wsEndpointConfigurator
)
210 wsServerContainer
.addEndpoint(config
);
211 } catch (DeploymentException e
) {
212 throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e
);
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("/");
225 httpContext
.setAttribute(CONTEXT_TEMPDIR
, tempDir
.toAbsolutePath().toFile());
226 SessionHandler handler
= new SessionHandler();
227 handler
.setMaxInactiveInterval(-1);
228 httpContext
.setSessionHandler(handler
);
233 private String
httpPortsMsg() {
235 return (httpConnector
!= null ?
"HTTP " + getHttpPort() + " " : " ")
236 + (httpsConnector
!= null ?
"HTTPS " + getHttpsPort() : "");
239 private String
getFrameworkProp(CmsDeployProperty deployProperty
) {
240 return cmsState
.getDeployProperty(deployProperty
.getProperty());
243 public void setCmsState(CmsState cmsState
) {
244 this.cmsState
= cmsState
;