1 package org
.argeo
.cms
.servlet
.internal
.jetty
;
3 import java
.util
.Dictionary
;
4 import java
.util
.Hashtable
;
6 import java
.util
.concurrent
.ForkJoinPool
;
8 import javax
.websocket
.DeploymentException
;
9 import javax
.websocket
.server
.ServerContainer
;
10 import javax
.websocket
.server
.ServerEndpointConfig
;
12 import org
.argeo
.api
.cms
.CmsConstants
;
13 import org
.argeo
.api
.cms
.CmsLog
;
14 import org
.argeo
.api
.cms
.CmsState
;
15 import org
.argeo
.cms
.CmsDeployProperty
;
16 import org
.argeo
.cms
.websocket
.javax
.server
.CmsWebSocketConfigurator
;
17 import org
.argeo
.cms
.websocket
.javax
.server
.TestEndpoint
;
18 import org
.argeo
.util
.LangUtils
;
19 import org
.eclipse
.equinox
.http
.jetty
.JettyConfigurator
;
20 import org
.osgi
.framework
.BundleContext
;
21 import org
.osgi
.framework
.FrameworkUtil
;
22 import org
.osgi
.framework
.ServiceReference
;
23 import org
.osgi
.util
.tracker
.ServiceTracker
;
25 public class JettyConfig
{
26 private final static CmsLog log
= CmsLog
.getLog(JettyConfig
.class);
28 final static String CMS_JETTY_CUSTOMIZER_CLASS
= "org.argeo.equinox.jetty.CmsJettyCustomizer";
30 private CmsState cmsState
;
32 private final BundleContext bc
= FrameworkUtil
.getBundle(JettyConfig
.class).getBundleContext();
34 // private static final String JETTY_PROPERTY_PREFIX =
35 // "org.eclipse.equinox.http.jetty.";
38 // We need to start asynchronously so that Jetty bundle get started by lazy init
39 // due to the non-configurable behaviour of its activator
40 ForkJoinPool
.commonPool().execute(() -> {
41 Dictionary
<String
, ?
> properties
= getHttpServerConfig();
42 startServer(properties
);
45 ServiceTracker
<ServerContainer
, ServerContainer
> serverSt
= new ServiceTracker
<ServerContainer
, ServerContainer
>(
46 bc
, ServerContainer
.class, null) {
49 public ServerContainer
addingService(ServiceReference
<ServerContainer
> reference
) {
50 ServerContainer serverContainer
= super.addingService(reference
);
52 BundleContext bc
= reference
.getBundle().getBundleContext();
53 ServiceReference
<ServerEndpointConfig
.Configurator
> srConfigurator
= bc
54 .getServiceReference(ServerEndpointConfig
.Configurator
.class);
55 ServerEndpointConfig
.Configurator endpointConfigurator
= bc
.getService(srConfigurator
);
56 ServerEndpointConfig config
= ServerEndpointConfig
.Builder
57 .create(TestEndpoint
.class, "/ws/test/events/").configurator(endpointConfigurator
).build();
59 serverContainer
.addEndpoint(config
);
60 } catch (DeploymentException e
) {
61 throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e
);
63 return serverContainer
;
69 // check initialisation
70 // ServiceTracker<?, ?> httpSt = new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, null) {
73 // public HttpService addingService(ServiceReference<HttpService> sr) {
74 // Object httpPort = sr.getProperty("http.port");
75 // Object httpsPort = sr.getProperty("https.port");
76 // log.info(httpPortsMsg(httpPort, httpsPort));
78 // return super.addingService(sr);
86 JettyConfigurator
.stopServer(CmsConstants
.DEFAULT
);
87 } catch (Exception e
) {
88 log
.error("Cannot stop default Jetty server.", e
);
93 public void startServer(Dictionary
<String
, ?
> properties
) {
94 // Explicitly configures Jetty so that the default server is not started by the
95 // activator of the Equinox Jetty bundle.
96 Map
<String
, String
> config
= LangUtils
.dictToStringMap(properties
);
97 if (!config
.isEmpty()) {
98 config
.put("customizer.class", CMS_JETTY_CUSTOMIZER_CLASS
);
100 // TODO centralise with Jetty extender
101 Object webSocketEnabled
= config
.get(CmsDeployProperty
.WEBSOCKET_ENABLED
.getProperty());
102 if (webSocketEnabled
!= null && webSocketEnabled
.toString().equals("true")) {
103 bc
.registerService(ServerEndpointConfig
.Configurator
.class, new CmsWebSocketConfigurator(), null);
104 // config.put(WEBSOCKET_ENABLED, "true");
108 long begin
= System
.currentTimeMillis();
111 while (tryCount
> 0) {
113 // FIXME deal with multiple ids
114 JettyConfigurator
.startServer(CmsConstants
.DEFAULT
, new Hashtable
<>(config
));
116 Object httpPort
= config
.get(JettyHttpConstants
.HTTP_PORT
);
117 Object httpsPort
= config
.get(JettyHttpConstants
.HTTPS_PORT
);
118 log
.info(httpPortsMsg(httpPort
, httpsPort
));
120 // Explicitly starts Jetty OSGi HTTP bundle, so that it gets triggered if OSGi
121 // configuration is not cleaned
122 FrameworkUtil
.getBundle(JettyConfigurator
.class).start();
124 } catch (IllegalStateException e
) {
125 // e.printStackTrace();
126 // Jetty may not be ready
129 } catch (Exception e1
) {
135 long duration
= System
.currentTimeMillis() - begin
;
136 log
.error("Gave up with starting Jetty server after " + (duration
/ 1000) + " s");
137 } catch (Exception e
) {
138 log
.error("Cannot start default Jetty server with config " + properties
, e
);
143 private String
httpPortsMsg(Object httpPort
, Object httpsPort
) {
144 return (httpPort
!= null ?
"HTTP " + httpPort
+ " " : " ") + (httpsPort
!= null ?
"HTTPS " + httpsPort
: "");
147 /** Override the provided config with the framework properties */
148 public Dictionary
<String
, Object
> getHttpServerConfig() {
149 String httpPort
= getFrameworkProp(CmsDeployProperty
.HTTP_PORT
);
150 String httpsPort
= getFrameworkProp(CmsDeployProperty
.HTTPS_PORT
);
151 /// TODO make it more generic
152 String httpHost
= getFrameworkProp(CmsDeployProperty
.HOST
);
153 // String httpsHost = getFrameworkProp(
154 // JettyConfig.JETTY_PROPERTY_PREFIX + CmsHttpConstants.HTTPS_HOST);
155 String webSocketEnabled
= getFrameworkProp(CmsDeployProperty
.WEBSOCKET_ENABLED
);
157 final Hashtable
<String
, Object
> props
= new Hashtable
<String
, Object
>();
159 if (httpPort
!= null || httpsPort
!= null) {
160 boolean httpEnabled
= httpPort
!= null;
161 props
.put(JettyHttpConstants
.HTTP_ENABLED
, httpEnabled
);
162 boolean httpsEnabled
= httpsPort
!= null;
163 props
.put(JettyHttpConstants
.HTTPS_ENABLED
, httpsEnabled
);
166 props
.put(JettyHttpConstants
.HTTP_PORT
, httpPort
);
167 if (httpHost
!= null)
168 props
.put(JettyHttpConstants
.HTTP_HOST
, httpHost
);
172 props
.put(JettyHttpConstants
.HTTPS_PORT
, httpsPort
);
173 if (httpHost
!= null)
174 props
.put(JettyHttpConstants
.HTTPS_HOST
, httpHost
);
177 props
.put(JettyHttpConstants
.SSL_KEYSTORETYPE
, getFrameworkProp(CmsDeployProperty
.SSL_KEYSTORETYPE
));
178 props
.put(JettyHttpConstants
.SSL_KEYSTORE
, getFrameworkProp(CmsDeployProperty
.SSL_KEYSTORE
));
179 props
.put(JettyHttpConstants
.SSL_PASSWORD
, getFrameworkProp(CmsDeployProperty
.SSL_PASSWORD
));
182 props
.put(JettyHttpConstants
.SSL_TRUSTSTORETYPE
,
183 getFrameworkProp(CmsDeployProperty
.SSL_TRUSTSTORETYPE
));
184 props
.put(JettyHttpConstants
.SSL_TRUSTSTORE
, getFrameworkProp(CmsDeployProperty
.SSL_TRUSTSTORE
));
185 props
.put(JettyHttpConstants
.SSL_TRUSTSTOREPASSWORD
,
186 getFrameworkProp(CmsDeployProperty
.SSL_TRUSTSTOREPASSWORD
));
188 // client certificate authentication
189 String wantClientAuth
= getFrameworkProp(CmsDeployProperty
.SSL_WANTCLIENTAUTH
);
190 if (wantClientAuth
!= null)
191 props
.put(JettyHttpConstants
.SSL_WANTCLIENTAUTH
, Boolean
.parseBoolean(wantClientAuth
));
192 String needClientAuth
= getFrameworkProp(CmsDeployProperty
.SSL_NEEDCLIENTAUTH
);
193 if (needClientAuth
!= null)
194 props
.put(JettyHttpConstants
.SSL_NEEDCLIENTAUTH
, Boolean
.parseBoolean(needClientAuth
));
198 if (webSocketEnabled
!= null && webSocketEnabled
.equals("true"))
199 props
.put(CmsDeployProperty
.WEBSOCKET_ENABLED
.getProperty(), true);
201 props
.put(CmsConstants
.CN
, CmsConstants
.DEFAULT
);
206 private String
getFrameworkProp(CmsDeployProperty deployProperty
) {
207 return cmsState
.getDeployProperty(deployProperty
.getProperty());
210 public void setCmsState(CmsState cmsState
) {
211 this.cmsState
= cmsState
;