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 = "org.eclipse.equinox.http.jetty.";
37 // We need to start asynchronously so that Jetty bundle get started by lazy init
38 // due to the non-configurable behaviour of its activator
39 ForkJoinPool
.commonPool().execute(() -> {
40 Dictionary
<String
, ?
> properties
= getHttpServerConfig();
41 startServer(properties
);
44 ServiceTracker
<ServerContainer
, ServerContainer
> serverSt
= new ServiceTracker
<ServerContainer
, ServerContainer
>(
45 bc
, ServerContainer
.class, null) {
48 public ServerContainer
addingService(ServiceReference
<ServerContainer
> reference
) {
49 ServerContainer serverContainer
= super.addingService(reference
);
51 BundleContext bc
= reference
.getBundle().getBundleContext();
52 ServiceReference
<ServerEndpointConfig
.Configurator
> srConfigurator
= bc
53 .getServiceReference(ServerEndpointConfig
.Configurator
.class);
54 ServerEndpointConfig
.Configurator endpointConfigurator
= bc
.getService(srConfigurator
);
55 ServerEndpointConfig config
= ServerEndpointConfig
.Builder
56 .create(TestEndpoint
.class, "/ws/test/events/").configurator(endpointConfigurator
).build();
58 serverContainer
.addEndpoint(config
);
59 } catch (DeploymentException e
) {
60 throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e
);
62 return serverContainer
;
68 // check initialisation
69 // ServiceTracker<?, ?> httpSt = new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, null) {
72 // public HttpService addingService(ServiceReference<HttpService> sr) {
73 // Object httpPort = sr.getProperty("http.port");
74 // Object httpsPort = sr.getProperty("https.port");
75 // log.info(httpPortsMsg(httpPort, httpsPort));
77 // return super.addingService(sr);
85 JettyConfigurator
.stopServer(CmsConstants
.DEFAULT
);
86 } catch (Exception e
) {
87 log
.error("Cannot stop default Jetty server.", e
);
92 public void startServer(Dictionary
<String
, ?
> properties
) {
93 // Explicitly configures Jetty so that the default server is not started by the
94 // activator of the Equinox Jetty bundle.
95 Map
<String
, String
> config
= LangUtils
.dictToStringMap(properties
);
96 if (!config
.isEmpty()) {
97 config
.put("customizer.class", CMS_JETTY_CUSTOMIZER_CLASS
);
99 // TODO centralise with Jetty extender
100 Object webSocketEnabled
= config
.get(CmsDeployProperty
.WEBSOCKET_ENABLED
.getProperty());
101 if (webSocketEnabled
!= null && webSocketEnabled
.toString().equals("true")) {
102 bc
.registerService(ServerEndpointConfig
.Configurator
.class, new CmsWebSocketConfigurator(), null);
103 // config.put(WEBSOCKET_ENABLED, "true");
109 tryGettyJetty
: while (tryCount
> 0) {
111 // FIXME deal with multiple ids
112 JettyConfigurator
.startServer(CmsConstants
.DEFAULT
, new Hashtable
<>(config
));
114 Object httpPort
= config
.get(JettyHttpConstants
.HTTP_PORT
);
115 Object httpsPort
= config
.get(JettyHttpConstants
.HTTPS_PORT
);
116 log
.info(httpPortsMsg(httpPort
, httpsPort
));
118 // Explicitly starts Jetty OSGi HTTP bundle, so that it gets triggered if OSGi
119 // configuration is not cleaned
120 FrameworkUtil
.getBundle(JettyConfigurator
.class).start();
122 } catch (IllegalStateException e
) {
123 // e.printStackTrace();
124 // Jetty may not be ready
127 } catch (Exception e1
) {
133 } catch (Exception e
) {
134 log
.error("Cannot start default Jetty server with config " + properties
, e
);
139 private String
httpPortsMsg(Object httpPort
, Object httpsPort
) {
140 return (httpPort
!= null ?
"HTTP " + httpPort
+ " " : " ") + (httpsPort
!= null ?
"HTTPS " + httpsPort
: "");
143 /** Override the provided config with the framework properties */
144 public Dictionary
<String
, Object
> getHttpServerConfig() {
145 String httpPort
= getFrameworkProp(CmsDeployProperty
.HTTP_PORT
);
146 String httpsPort
= getFrameworkProp(CmsDeployProperty
.HTTPS_PORT
);
147 /// TODO make it more generic
148 String httpHost
= getFrameworkProp(CmsDeployProperty
.HOST
);
149 // String httpsHost = getFrameworkProp(
150 // JettyConfig.JETTY_PROPERTY_PREFIX + CmsHttpConstants.HTTPS_HOST);
151 String webSocketEnabled
= getFrameworkProp(CmsDeployProperty
.WEBSOCKET_ENABLED
);
153 final Hashtable
<String
, Object
> props
= new Hashtable
<String
, Object
>();
155 if (httpPort
!= null || httpsPort
!= null) {
156 boolean httpEnabled
= httpPort
!= null;
157 props
.put(JettyHttpConstants
.HTTP_ENABLED
, httpEnabled
);
158 boolean httpsEnabled
= httpsPort
!= null;
159 props
.put(JettyHttpConstants
.HTTPS_ENABLED
, httpsEnabled
);
162 props
.put(JettyHttpConstants
.HTTP_PORT
, httpPort
);
163 if (httpHost
!= null)
164 props
.put(JettyHttpConstants
.HTTP_HOST
, httpHost
);
168 props
.put(JettyHttpConstants
.HTTPS_PORT
, httpsPort
);
169 if (httpHost
!= null)
170 props
.put(JettyHttpConstants
.HTTPS_HOST
, httpHost
);
172 props
.put(JettyHttpConstants
.SSL_KEYSTORETYPE
, getFrameworkProp(CmsDeployProperty
.SSL_KEYSTORETYPE
));
173 props
.put(JettyHttpConstants
.SSL_KEYSTORE
, getFrameworkProp(CmsDeployProperty
.SSL_KEYSTORE
));
174 props
.put(JettyHttpConstants
.SSL_PASSWORD
, getFrameworkProp(CmsDeployProperty
.SSL_PASSWORD
));
176 // client certificate authentication
177 String wantClientAuth
= getFrameworkProp(CmsDeployProperty
.SSL_WANTCLIENTAUTH
);
178 if (wantClientAuth
!= null)
179 props
.put(JettyHttpConstants
.SSL_WANTCLIENTAUTH
, Boolean
.parseBoolean(wantClientAuth
));
180 String needClientAuth
= getFrameworkProp(CmsDeployProperty
.SSL_NEEDCLIENTAUTH
);
181 if (needClientAuth
!= null)
182 props
.put(JettyHttpConstants
.SSL_NEEDCLIENTAUTH
, Boolean
.parseBoolean(needClientAuth
));
186 if (webSocketEnabled
!= null && webSocketEnabled
.equals("true"))
187 props
.put(CmsDeployProperty
.WEBSOCKET_ENABLED
.getProperty(), true);
189 props
.put(CmsConstants
.CN
, CmsConstants
.DEFAULT
);
194 private String
getFrameworkProp(CmsDeployProperty deployProperty
) {
195 return cmsState
.getDeployProperty(deployProperty
.getProperty());
198 public void setCmsState(CmsState cmsState
) {
199 this.cmsState
= cmsState
;