]> git.argeo.org Git - lgpl/argeo-commons.git/blob - jetty/JettyConfig.java
Prepare next development cycle
[lgpl/argeo-commons.git] / jetty / JettyConfig.java
1 package org.argeo.cms.servlet.internal.jetty;
2
3 import java.io.File;
4 import java.util.Dictionary;
5 import java.util.Hashtable;
6 import java.util.Map;
7 import java.util.concurrent.ForkJoinPool;
8
9 import javax.websocket.DeploymentException;
10 import javax.websocket.server.ServerContainer;
11 import javax.websocket.server.ServerEndpointConfig;
12
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.javax.server.CmsWebSocketConfigurator;
18 import org.argeo.cms.websocket.javax.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;
26
27 public class JettyConfig {
28 private final static CmsLog log = CmsLog.getLog(JettyConfig.class);
29
30 final static String CMS_JETTY_CUSTOMIZER_CLASS = "org.argeo.equinox.jetty.CmsJettyCustomizer";
31
32 private CmsState cmsState;
33
34 private final BundleContext bc = FrameworkUtil.getBundle(JettyConfig.class).getBundleContext();
35
36 // private static final String JETTY_PROPERTY_PREFIX =
37 // "org.eclipse.equinox.http.jetty.";
38
39 public void start() {
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);
45 });
46
47 ServiceTracker<ServerContainer, ServerContainer> serverSt = new ServiceTracker<ServerContainer, ServerContainer>(
48 bc, ServerContainer.class, null) {
49
50 @Override
51 public ServerContainer addingService(ServiceReference<ServerContainer> reference) {
52 ServerContainer serverContainer = super.addingService(reference);
53
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();
60 try {
61 serverContainer.addEndpoint(config);
62 } catch (DeploymentException e) {
63 throw new IllegalStateException("Cannot initalise the WebSocket server runtime.", e);
64 }
65 return serverContainer;
66 }
67
68 };
69 serverSt.open();
70
71 // check initialisation
72 // ServiceTracker<?, ?> httpSt = new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, null) {
73 //
74 // @Override
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));
79 // close();
80 // return super.addingService(sr);
81 // }
82 // };
83 // httpSt.open();
84 }
85
86 public void stop() {
87 try {
88 JettyConfigurator.stopServer(CmsConstants.DEFAULT);
89 } catch (Exception e) {
90 log.error("Cannot stop default Jetty server.", e);
91 }
92
93 }
94
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);
101
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");
107 }
108 }
109
110 properties.put(Constants.SERVICE_PID, "default");
111 File jettyWorkDir = new File(bc.getDataFile(""), "jettywork"); //$NON-NLS-1$
112 jettyWorkDir.mkdir();
113
114 // HttpServerManager serverManager = new HttpServerManager(jettyWorkDir);
115 // try {
116 // serverManager.updated("default", properties);
117 // } catch (ConfigurationException e) {
118 // // TODO Auto-generated catch block
119 // e.printStackTrace();
120 // }
121 Object httpPort = config.get(JettyHttpConstants.HTTP_PORT);
122 Object httpsPort = config.get(JettyHttpConstants.HTTPS_PORT);
123 log.info(httpPortsMsg(httpPort, httpsPort));
124
125 // long begin = System.currentTimeMillis();
126 // int tryCount = 60;
127 // try {
128 // while (tryCount > 0) {
129 // try {
130 // // FIXME deal with multiple ids
131 // JettyConfigurator.startServer(CmsConstants.DEFAULT, new Hashtable<>(config));
132 //
133 // Object httpPort = config.get(JettyHttpConstants.HTTP_PORT);
134 // Object httpsPort = config.get(JettyHttpConstants.HTTPS_PORT);
135 // log.info(httpPortsMsg(httpPort, httpsPort));
136 //
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();
140 // return;
141 // } catch (IllegalStateException e) {
142 // // e.printStackTrace();
143 // // Jetty may not be ready
144 // try {
145 // Thread.sleep(1000);
146 // } catch (Exception e1) {
147 // // silent
148 // }
149 // tryCount--;
150 // }
151 // }
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);
156 // }
157
158 }
159
160 private String httpPortsMsg(Object httpPort, Object httpsPort) {
161 return (httpPort != null ? "HTTP " + httpPort + " " : " ") + (httpsPort != null ? "HTTPS " + httpsPort : "");
162 }
163
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);
173
174 final Hashtable<String, Object> props = new Hashtable<String, Object>();
175 // try {
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);
181
182 if (httpEnabled) {
183 props.put(JettyHttpConstants.HTTP_PORT, httpPort);
184 if (httpHost != null)
185 props.put(JettyHttpConstants.HTTP_HOST, httpHost);
186 }
187
188 if (httpsEnabled) {
189 props.put(JettyHttpConstants.HTTPS_PORT, httpsPort);
190 if (httpHost != null)
191 props.put(JettyHttpConstants.HTTPS_HOST, httpHost);
192
193 // keystore
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));
197
198 // truststore
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));
204
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));
212 }
213
214 // web socket
215 if (webSocketEnabled != null && webSocketEnabled.equals("true"))
216 props.put(CmsDeployProperty.WEBSOCKET_ENABLED.getProperty(), true);
217
218 props.put(CmsConstants.CN, CmsConstants.DEFAULT);
219 }
220 return props;
221 }
222
223 private String getFrameworkProp(CmsDeployProperty deployProperty) {
224 return cmsState.getDeployProperty(deployProperty.getProperty());
225 }
226
227 public void setCmsState(CmsState cmsState) {
228 this.cmsState = cmsState;
229 }
230
231 }