1 package org
.argeo
.cms
.servlet
.internal
.jetty
;
4 import java
.util
.Dictionary
;
5 import java
.util
.Hashtable
;
7 import java
.util
.concurrent
.ForkJoinPool
;
9 import javax
.websocket
.DeploymentException
;
10 import javax
.websocket
.server
.ServerContainer
;
11 import javax
.websocket
.server
.ServerEndpointConfig
;
13 import org
.argeo
.api
.cms
.CmsConstants
;
14 import org
.argeo
.api
.cms
.CmsLog
;
15 import org
.argeo
.api
.cms
.CmsState
;
16 import org
.argeo
.cms
.CmsDeployProperty
;
17 import org
.argeo
.cms
.websocket
.server
.CmsWebSocketConfigurator
;
18 import org
.argeo
.cms
.websocket
.server
.TestEndpoint
;
19 import org
.argeo
.util
.LangUtils
;
20 import org
.eclipse
.equinox
.http
.jetty
.JettyConfigurator
;
21 import org
.osgi
.framework
.BundleContext
;
22 import org
.osgi
.framework
.Constants
;
23 import org
.osgi
.framework
.FrameworkUtil
;
24 import org
.osgi
.framework
.ServiceReference
;
25 import org
.osgi
.util
.tracker
.ServiceTracker
;
27 public class JettyConfig
{
28 private final static CmsLog log
= CmsLog
.getLog(JettyConfig
.class);
30 final static String CMS_JETTY_CUSTOMIZER_CLASS
= "org.argeo.equinox.jetty.CmsJettyCustomizer";
32 private CmsState cmsState
;
34 private final BundleContext bc
= FrameworkUtil
.getBundle(JettyConfig
.class).getBundleContext();
36 // private static final String JETTY_PROPERTY_PREFIX =
37 // "org.eclipse.equinox.http.jetty.";
40 // We need to start asynchronously so that Jetty bundle get started by lazy init
41 // due to the non-configurable behaviour of its activator
42 ForkJoinPool
.commonPool().execute(() -> {
43 Dictionary
<String
, Object
> properties
= getHttpServerConfig();
44 startServer(properties
);
47 ServiceTracker
<ServerContainer
, ServerContainer
> serverSt
= new ServiceTracker
<ServerContainer
, ServerContainer
>(
48 bc
, ServerContainer
.class, null) {
51 public ServerContainer
addingService(ServiceReference
<ServerContainer
> reference
) {
52 ServerContainer serverContainer
= super.addingService(reference
);
54 BundleContext bc
= reference
.getBundle().getBundleContext();
55 ServiceReference
<ServerEndpointConfig
.Configurator
> srConfigurator
= bc
56 .getServiceReference(ServerEndpointConfig
.Configurator
.class);
57 ServerEndpointConfig
.Configurator endpointConfigurator
= bc
.getService(srConfigurator
);
58 ServerEndpointConfig config
= ServerEndpointConfig
.Builder
59 .create(TestEndpoint
.class, "/ws/test/events/").configurator(endpointConfigurator
).build();
61 serverContainer
.addEndpoint(config
);
62 } catch (DeploymentException e
) {
63 throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e
);
65 return serverContainer
;
71 // check initialisation
72 // ServiceTracker<?, ?> httpSt = new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, null) {
75 // public HttpService addingService(ServiceReference<HttpService> sr) {
76 // Object httpPort = sr.getProperty("http.port");
77 // Object httpsPort = sr.getProperty("https.port");
78 // log.info(httpPortsMsg(httpPort, httpsPort));
80 // return super.addingService(sr);
88 JettyConfigurator
.stopServer(CmsConstants
.DEFAULT
);
89 } catch (Exception e
) {
90 log
.error("Cannot stop default Jetty server.", e
);
95 public void startServer(Dictionary
<String
, Object
> properties
) {
96 // Explicitly configures Jetty so that the default server is not started by the
97 // activator of the Equinox Jetty bundle.
98 Map
<String
, String
> config
= LangUtils
.dictToStringMap(properties
);
99 if (!config
.isEmpty()) {
100 config
.put("customizer.class", CMS_JETTY_CUSTOMIZER_CLASS
);
102 // TODO centralise with Jetty extender
103 Object webSocketEnabled
= config
.get(CmsDeployProperty
.WEBSOCKET_ENABLED
.getProperty());
104 if (webSocketEnabled
!= null && webSocketEnabled
.toString().equals("true")) {
105 bc
.registerService(ServerEndpointConfig
.Configurator
.class, new CmsWebSocketConfigurator(), null);
106 // config.put(WEBSOCKET_ENABLED, "true");
110 properties
.put(Constants
.SERVICE_PID
, "default");
111 File jettyWorkDir
= new File(bc
.getDataFile(""), "jettywork"); //$NON-NLS-1$
112 jettyWorkDir
.mkdir();
114 // HttpServerManager serverManager = new HttpServerManager(jettyWorkDir);
116 // serverManager.updated("default", properties);
117 // } catch (ConfigurationException e) {
118 // // TODO Auto-generated catch block
119 // e.printStackTrace();
121 Object httpPort
= config
.get(JettyHttpConstants
.HTTP_PORT
);
122 Object httpsPort
= config
.get(JettyHttpConstants
.HTTPS_PORT
);
123 log
.info(httpPortsMsg(httpPort
, httpsPort
));
125 // long begin = System.currentTimeMillis();
126 // int tryCount = 60;
128 // while (tryCount > 0) {
130 // // FIXME deal with multiple ids
131 // JettyConfigurator.startServer(CmsConstants.DEFAULT, new Hashtable<>(config));
133 // Object httpPort = config.get(JettyHttpConstants.HTTP_PORT);
134 // Object httpsPort = config.get(JettyHttpConstants.HTTPS_PORT);
135 // log.info(httpPortsMsg(httpPort, httpsPort));
137 // // Explicitly starts Jetty OSGi HTTP bundle, so that it gets triggered if OSGi
138 // // configuration is not cleaned
139 // FrameworkUtil.getBundle(JettyConfigurator.class).start();
141 // } catch (IllegalStateException e) {
142 // // e.printStackTrace();
143 // // Jetty may not be ready
145 // Thread.sleep(1000);
146 // } catch (Exception e1) {
152 // long duration = System.currentTimeMillis() - begin;
153 // log.error("Gave up with starting Jetty server after " + (duration / 1000) + " s");
154 // } catch (Exception e) {
155 // log.error("Cannot start default Jetty server with config " + properties, e);
160 private String
httpPortsMsg(Object httpPort
, Object httpsPort
) {
161 return (httpPort
!= null ?
"HTTP " + httpPort
+ " " : " ") + (httpsPort
!= null ?
"HTTPS " + httpsPort
: "");
164 /** Override the provided config with the framework properties */
165 public Dictionary
<String
, Object
> getHttpServerConfig() {
166 String httpPort
= getFrameworkProp(CmsDeployProperty
.HTTP_PORT
);
167 String httpsPort
= getFrameworkProp(CmsDeployProperty
.HTTPS_PORT
);
168 /// TODO make it more generic
169 String httpHost
= getFrameworkProp(CmsDeployProperty
.HOST
);
170 // String httpsHost = getFrameworkProp(
171 // JettyConfig.JETTY_PROPERTY_PREFIX + CmsHttpConstants.HTTPS_HOST);
172 String webSocketEnabled
= getFrameworkProp(CmsDeployProperty
.WEBSOCKET_ENABLED
);
174 final Hashtable
<String
, Object
> props
= new Hashtable
<String
, Object
>();
176 if (httpPort
!= null || httpsPort
!= null) {
177 boolean httpEnabled
= httpPort
!= null;
178 props
.put(JettyHttpConstants
.HTTP_ENABLED
, httpEnabled
);
179 boolean httpsEnabled
= httpsPort
!= null;
180 props
.put(JettyHttpConstants
.HTTPS_ENABLED
, httpsEnabled
);
183 props
.put(JettyHttpConstants
.HTTP_PORT
, httpPort
);
184 if (httpHost
!= null)
185 props
.put(JettyHttpConstants
.HTTP_HOST
, httpHost
);
189 props
.put(JettyHttpConstants
.HTTPS_PORT
, httpsPort
);
190 if (httpHost
!= null)
191 props
.put(JettyHttpConstants
.HTTPS_HOST
, httpHost
);
194 props
.put(JettyHttpConstants
.SSL_KEYSTORETYPE
, getFrameworkProp(CmsDeployProperty
.SSL_KEYSTORETYPE
));
195 props
.put(JettyHttpConstants
.SSL_KEYSTORE
, getFrameworkProp(CmsDeployProperty
.SSL_KEYSTORE
));
196 props
.put(JettyHttpConstants
.SSL_PASSWORD
, getFrameworkProp(CmsDeployProperty
.SSL_PASSWORD
));
199 props
.put(JettyHttpConstants
.SSL_TRUSTSTORETYPE
,
200 getFrameworkProp(CmsDeployProperty
.SSL_TRUSTSTORETYPE
));
201 props
.put(JettyHttpConstants
.SSL_TRUSTSTORE
, getFrameworkProp(CmsDeployProperty
.SSL_TRUSTSTORE
));
202 props
.put(JettyHttpConstants
.SSL_TRUSTSTOREPASSWORD
,
203 getFrameworkProp(CmsDeployProperty
.SSL_TRUSTSTOREPASSWORD
));
205 // client certificate authentication
206 String wantClientAuth
= getFrameworkProp(CmsDeployProperty
.SSL_WANTCLIENTAUTH
);
207 if (wantClientAuth
!= null)
208 props
.put(JettyHttpConstants
.SSL_WANTCLIENTAUTH
, Boolean
.parseBoolean(wantClientAuth
));
209 String needClientAuth
= getFrameworkProp(CmsDeployProperty
.SSL_NEEDCLIENTAUTH
);
210 if (needClientAuth
!= null)
211 props
.put(JettyHttpConstants
.SSL_NEEDCLIENTAUTH
, Boolean
.parseBoolean(needClientAuth
));
215 if (webSocketEnabled
!= null && webSocketEnabled
.equals("true"))
216 props
.put(CmsDeployProperty
.WEBSOCKET_ENABLED
.getProperty(), true);
218 props
.put(CmsConstants
.CN
, CmsConstants
.DEFAULT
);
223 private String
getFrameworkProp(CmsDeployProperty deployProperty
) {
224 return cmsState
.getDeployProperty(deployProperty
.getProperty());
227 public void setCmsState(CmsState cmsState
) {
228 this.cmsState
= cmsState
;