]> git.argeo.org Git - lgpl/argeo-commons.git/blob - eclipse/org.argeo.cms.servlet/src/org/argeo/cms/servlet/internal/jetty/JettyConfig.java
0e2a3e5cab4e8594d9df364ffbe8d911f3799165
[lgpl/argeo-commons.git] / eclipse / org.argeo.cms.servlet / src / org / argeo / cms / servlet / internal / jetty / JettyConfig.java
1 package org.argeo.cms.servlet.internal.jetty;
2
3 import java.util.Dictionary;
4 import java.util.Hashtable;
5 import java.util.Map;
6 import java.util.concurrent.ForkJoinPool;
7
8 import javax.websocket.DeploymentException;
9 import javax.websocket.server.ServerContainer;
10 import javax.websocket.server.ServerEndpointConfig;
11
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;
24
25 public class JettyConfig {
26 private final static CmsLog log = CmsLog.getLog(JettyConfig.class);
27
28 final static String CMS_JETTY_CUSTOMIZER_CLASS = "org.argeo.equinox.jetty.CmsJettyCustomizer";
29
30 private CmsState cmsState;
31
32 private final BundleContext bc = FrameworkUtil.getBundle(JettyConfig.class).getBundleContext();
33
34 // private static final String JETTY_PROPERTY_PREFIX =
35 // "org.eclipse.equinox.http.jetty.";
36
37 public void start() {
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);
43 });
44
45 ServiceTracker<ServerContainer, ServerContainer> serverSt = new ServiceTracker<ServerContainer, ServerContainer>(
46 bc, ServerContainer.class, null) {
47
48 @Override
49 public ServerContainer addingService(ServiceReference<ServerContainer> reference) {
50 ServerContainer serverContainer = super.addingService(reference);
51
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();
58 try {
59 serverContainer.addEndpoint(config);
60 } catch (DeploymentException e) {
61 throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e);
62 }
63 return serverContainer;
64 }
65
66 };
67 serverSt.open();
68
69 // check initialisation
70 // ServiceTracker<?, ?> httpSt = new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, null) {
71 //
72 // @Override
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));
77 // close();
78 // return super.addingService(sr);
79 // }
80 // };
81 // httpSt.open();
82 }
83
84 public void stop() {
85 try {
86 JettyConfigurator.stopServer(CmsConstants.DEFAULT);
87 } catch (Exception e) {
88 log.error("Cannot stop default Jetty server.", e);
89 }
90
91 }
92
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);
99
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");
105 }
106 }
107
108 long begin = System.currentTimeMillis();
109 int tryCount = 60;
110 try {
111 while (tryCount > 0) {
112 try {
113 // FIXME deal with multiple ids
114 JettyConfigurator.startServer(CmsConstants.DEFAULT, new Hashtable<>(config));
115
116 Object httpPort = config.get(JettyHttpConstants.HTTP_PORT);
117 Object httpsPort = config.get(JettyHttpConstants.HTTPS_PORT);
118 log.info(httpPortsMsg(httpPort, httpsPort));
119
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();
123 return;
124 } catch (IllegalStateException e) {
125 // e.printStackTrace();
126 // Jetty may not be ready
127 try {
128 Thread.sleep(1000);
129 } catch (Exception e1) {
130 // silent
131 }
132 tryCount--;
133 }
134 long duration = System.currentTimeMillis() - begin;
135 log.error("Gave up with starting Jetty server after " + (duration / 1000) + " s");
136 }
137 } catch (Exception e) {
138 log.error("Cannot start default Jetty server with config " + properties, e);
139 }
140
141 }
142
143 private String httpPortsMsg(Object httpPort, Object httpsPort) {
144 return (httpPort != null ? "HTTP " + httpPort + " " : " ") + (httpsPort != null ? "HTTPS " + httpsPort : "");
145 }
146
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);
156
157 final Hashtable<String, Object> props = new Hashtable<String, Object>();
158 // try {
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);
164
165 if (httpEnabled) {
166 props.put(JettyHttpConstants.HTTP_PORT, httpPort);
167 if (httpHost != null)
168 props.put(JettyHttpConstants.HTTP_HOST, httpHost);
169 }
170
171 if (httpsEnabled) {
172 props.put(JettyHttpConstants.HTTPS_PORT, httpsPort);
173 if (httpHost != null)
174 props.put(JettyHttpConstants.HTTPS_HOST, httpHost);
175
176 // keystore
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));
180
181 // truststore
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));
187
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));
195 }
196
197 // web socket
198 if (webSocketEnabled != null && webSocketEnabled.equals("true"))
199 props.put(CmsDeployProperty.WEBSOCKET_ENABLED.getProperty(), true);
200
201 props.put(CmsConstants.CN, CmsConstants.DEFAULT);
202 }
203 return props;
204 }
205
206 private String getFrameworkProp(CmsDeployProperty deployProperty) {
207 return cmsState.getDeployProperty(deployProperty.getProperty());
208 }
209
210 public void setCmsState(CmsState cmsState) {
211 this.cmsState = cmsState;
212 }
213
214 }