From d9ff37f84e799028a1a0300850eccae77ced2024 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Sun, 8 Sep 2019 10:18:30 +0200 Subject: [PATCH] Make WebSocket activation configurable. --- demo/cms-e4-rap.properties | 1 + .../cms/internal/http/HttpConstants.java | 32 ++++--- .../cms/internal/kernel/DeployConfig.java | 3 +- .../argeo/cms/internal/kernel/InitUtils.java | 6 ++ .../equinox/jetty/CmsJettyCustomizer.java | 51 ++++++++++ .../jetty/WebSocketJettyCustomizer.java | 95 ------------------- 6 files changed, 77 insertions(+), 111 deletions(-) create mode 100644 org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/CmsJettyCustomizer.java delete mode 100644 org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/WebSocketJettyCustomizer.java diff --git a/demo/cms-e4-rap.properties b/demo/cms-e4-rap.properties index 50d8e2b8e..bbfb30655 100644 --- a/demo/cms-e4-rap.properties +++ b/demo/cms-e4-rap.properties @@ -19,6 +19,7 @@ org.argeo.cms.e4.rap argeo.node.repo.type=h2 org.osgi.service.http.port=7070 #org.osgi.service.http.port.secure=7073 +#org.eclipse.equinox.http.jetty.websocket.enabled=true # Logging log4j.configuration=file:../../log4j.properties diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/HttpConstants.java b/org.argeo.cms/src/org/argeo/cms/internal/http/HttpConstants.java index 5fe57b7c2..51760fcff 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/http/HttpConstants.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/HttpConstants.java @@ -2,20 +2,22 @@ package org.argeo.cms.internal.http; /** Compatible with Jetty. */ public interface HttpConstants { - public static final String HTTP_ENABLED = "http.enabled"; - public static final String HTTP_PORT = "http.port"; - public static final String HTTP_HOST = "http.host"; - public static final String HTTPS_ENABLED = "https.enabled"; - public static final String HTTPS_HOST = "https.host"; - public static final String HTTPS_PORT = "https.port"; - public static final String SSL_KEYSTORE = "ssl.keystore"; - public static final String SSL_PASSWORD = "ssl.password"; - public static final String SSL_KEYPASSWORD = "ssl.keypassword"; - public static final String SSL_NEEDCLIENTAUTH = "ssl.needclientauth"; - public static final String SSL_WANTCLIENTAUTH = "ssl.wantclientauth"; - public static final String SSL_PROTOCOL = "ssl.protocol"; - public static final String SSL_ALGORITHM = "ssl.algorithm"; - public static final String SSL_KEYSTORETYPE = "ssl.keystoretype"; - public static final String JETTY_PROPERTY_PREFIX = "org.eclipse.equinox.http.jetty."; + static final String HTTP_ENABLED = "http.enabled"; + static final String HTTP_PORT = "http.port"; + static final String HTTP_HOST = "http.host"; + static final String HTTPS_ENABLED = "https.enabled"; + static final String HTTPS_HOST = "https.host"; + static final String HTTPS_PORT = "https.port"; + static final String SSL_KEYSTORE = "ssl.keystore"; + static final String SSL_PASSWORD = "ssl.password"; + static final String SSL_KEYPASSWORD = "ssl.keypassword"; + static final String SSL_NEEDCLIENTAUTH = "ssl.needclientauth"; + static final String SSL_WANTCLIENTAUTH = "ssl.wantclientauth"; + static final String SSL_PROTOCOL = "ssl.protocol"; + static final String SSL_ALGORITHM = "ssl.algorithm"; + static final String SSL_KEYSTORETYPE = "ssl.keystoretype"; + static final String JETTY_PROPERTY_PREFIX = "org.eclipse.equinox.http.jetty."; + // Argeo specific + static final String WEB_SOCKET_ENABLED = "websocket.enabled"; } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java index 3cce7e821..b1e36633a 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DeployConfig.java @@ -123,7 +123,8 @@ class DeployConfig implements ConfigurationListener { Dictionary webServerConfig = InitUtils .getHttpServerConfig(getProps(KernelConstants.JETTY_FACTORY_PID, NodeConstants.DEFAULT)); if (!webServerConfig.isEmpty()) { - webServerConfig.put("customizer.class", "org.argeo.equinox.jetty.WebSocketJettyCustomizer"); + // TODO chekc for other customizers + webServerConfig.put("customizer.class", "org.argeo.equinox.jetty.CmsJettyCustomizer"); putFactoryDeployConfig(KernelConstants.JETTY_FACTORY_PID, webServerConfig); } save(); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/InitUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/InitUtils.java index a4892503d..045130ecb 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/InitUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/InitUtils.java @@ -68,6 +68,8 @@ class InitUtils { /// TODO make it more generic String httpHost = getFrameworkProp(HttpConstants.JETTY_PROPERTY_PREFIX + HttpConstants.HTTP_HOST); String httpsHost = getFrameworkProp(HttpConstants.JETTY_PROPERTY_PREFIX + HttpConstants.HTTPS_HOST); + String webSocketEnabled = getFrameworkProp( + HttpConstants.JETTY_PROPERTY_PREFIX + HttpConstants.WEB_SOCKET_ENABLED); final Hashtable props = new Hashtable(); // try { @@ -101,6 +103,10 @@ class InitUtils { if (httpsHost != null) props.put(HttpConstants.HTTPS_HOST, httpHost); + if (webSocketEnabled != null) + if (webSocketEnabled.equals("true")) + props.put(HttpConstants.WEB_SOCKET_ENABLED, true); + props.put(NodeConstants.CN, NodeConstants.DEFAULT); } return props; diff --git a/org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/CmsJettyCustomizer.java b/org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/CmsJettyCustomizer.java new file mode 100644 index 000000000..60d23719e --- /dev/null +++ b/org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/CmsJettyCustomizer.java @@ -0,0 +1,51 @@ +package org.argeo.equinox.jetty; + +import java.util.Dictionary; + +import javax.servlet.ServletException; + +import org.eclipse.equinox.http.jetty.JettyCustomizer; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.websocket.jsr356.server.ServerContainer; +import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; + +/** Customises the Jetty HTTP server. */ +public class CmsJettyCustomizer extends JettyCustomizer { + private BundleContext bc = FrameworkUtil.getBundle(CmsJettyCustomizer.class).getBundleContext(); + + @Override + public Object customizeContext(Object context, Dictionary settings) { + // WebSocket + Object webSocketEnabled = settings.get("websocket.enabled"); + if (webSocketEnabled != null && webSocketEnabled.toString().equals("true")) { + ServletContextHandler servletContextHandler = (ServletContextHandler) context; + new WebSocketInit(servletContextHandler).start(); + } + return super.customizeContext(context, settings); + + } + + /** Configure websocket container asynchronously as it may take some time */ + private class WebSocketInit extends Thread { + ServletContextHandler servletContextHandler; + + public WebSocketInit(ServletContextHandler servletContextHandler) { + super("WebSocket Init"); + this.servletContextHandler = servletContextHandler; + } + + @Override + public void run() { + ServerContainer serverContainer; + try { + serverContainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler); + } catch (ServletException e) { + throw new IllegalStateException("Cannot configure web sockets", e); + } + bc.registerService(javax.websocket.server.ServerContainer.class, serverContainer, null); + } + + } +} diff --git a/org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/WebSocketJettyCustomizer.java b/org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/WebSocketJettyCustomizer.java deleted file mode 100644 index f582a43bc..000000000 --- a/org.argeo.ext.equinox.jetty/src/org/argeo/equinox/jetty/WebSocketJettyCustomizer.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.argeo.equinox.jetty; - -import java.util.Dictionary; - -import javax.servlet.ServletException; - -import org.eclipse.equinox.http.jetty.JettyCustomizer; -import org.eclipse.jetty.servlet.ServletContextHandler; -import org.eclipse.jetty.websocket.jsr356.server.ServerContainer; -import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer; -import org.osgi.framework.BundleContext; -import org.osgi.framework.FrameworkUtil; - -public class WebSocketJettyCustomizer extends JettyCustomizer { - private BundleContext bc = FrameworkUtil.getBundle(WebSocketJettyCustomizer.class).getBundleContext(); - - @Override - public Object customizeContext(Object context, Dictionary settings) { - ServletContextHandler servletContextHandler = (ServletContextHandler) context; - new WebSocketInit(servletContextHandler).start(); - return super.customizeContext(context, settings); - } - - /** Configure websocket container asynchronously as it may take some time */ - private class WebSocketInit extends Thread { - ServletContextHandler servletContextHandler; - - public WebSocketInit(ServletContextHandler servletContextHandler) { - super("WebSocket Init"); - this.servletContextHandler = servletContextHandler; - } - - @Override - public void run() { - ServerContainer serverContainer; - try { - serverContainer = WebSocketServerContainerInitializer.configureContext(servletContextHandler); -// serverContainer.addSessionListener(new WebSocketSessionListener() { -// -// @Override -// public void onSessionOpened(WebSocketSession session) { -// UpgradeRequest upgradeRequest = session.getUpgradeRequest(); -// UpgradeResponse upgradeResponse = session.getUpgradeResponse(); -// List acceptHeader = upgradeResponse.getHeaders("Sec-WebSocket-Accept"); -// if (acceptHeader.contains("no")) -// try { -// upgradeResponse.sendForbidden("FORBIDDEN"); -// return; -// } catch (IOException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// List cookies = upgradeRequest.getCookies(); -// -// System.out.println("Upgrade request cookies : " + cookies); -// String httpSessionId = null; -// if (cookies != null) { -// for (HttpCookie cookie : cookies) { -// if (cookie.getName().equals("JSESSIONID")) { -// httpSessionId = cookie.getValue(); -// } -// } -// } -// -// if (httpSessionId == null) { -// HttpSession httpSession = (HttpSession) upgradeRequest.getSession(); -// if (httpSession == null) { -//// session.disconnect(); -//// return; -// } else { -// httpSessionId = httpSession.getId(); -// System.out.println("Upgrade request session ID : " + httpSession.getId()); -// } -// } -// -// if (httpSessionId != null) { -// int dotIdx = httpSessionId.lastIndexOf('.'); -// if (dotIdx > 0) { -// httpSessionId = httpSessionId.substring(0, dotIdx); -// } -// } -// } -// -// @Override -// public void onSessionClosed(WebSocketSession session) { -// } -// }); - } catch (ServletException e) { - throw new IllegalStateException("Cannot configure web sockets", e); - } - bc.registerService(javax.websocket.server.ServerContainer.class, serverContainer, null); - } - - } -} -- 2.30.2