This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push: new 28b6cec Add POJO support to programmatic http -> ws upgrade 28b6cec is described below commit 28b6cec455cb970260c7559790c944b4cb981158 Author: Mark Thomas <ma...@apache.org> AuthorDate: Wed Dec 15 20:21:43 2021 +0000 Add POJO support to programmatic http -> ws upgrade --- .../websocket/server/LocalStrings.properties | 1 + .../tomcat/websocket/server/UpgradeUtil.java | 30 +++++++++++++++++++--- .../tomcat/websocket/server/WsServerContainer.java | 11 ++++++++ webapps/docs/changelog.xml | 5 ++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/java/org/apache/tomcat/websocket/server/LocalStrings.properties b/java/org/apache/tomcat/websocket/server/LocalStrings.properties index 16fdaf2..3698b90 100644 --- a/java/org/apache/tomcat/websocket/server/LocalStrings.properties +++ b/java/org/apache/tomcat/websocket/server/LocalStrings.properties @@ -22,6 +22,7 @@ serverContainer.missingAnnotation=Cannot deploy POJO class [{0}] as it is not an serverContainer.servletContextMissing=No ServletContext was specified upgradeUtil.incompatibleRsv=Extensions were specified that have incompatible RSV bit usage +upgradeUtil.pojoMpaFail=Unable to complete method mapping for POJO class [{0}] uriTemplate.duplicateParameter=The parameter [{0}] appears more than once in the path which is not permitted uriTemplate.emptySegment=The path [{0}] contains one or more empty segments which is not permitted diff --git a/java/org/apache/tomcat/websocket/server/UpgradeUtil.java b/java/org/apache/tomcat/websocket/server/UpgradeUtil.java index 5a07c93..5201a43 100644 --- a/java/org/apache/tomcat/websocket/server/UpgradeUtil.java +++ b/java/org/apache/tomcat/websocket/server/UpgradeUtil.java @@ -31,6 +31,8 @@ import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import jakarta.websocket.DeploymentException; +import jakarta.websocket.Endpoint; import jakarta.websocket.Extension; import jakarta.websocket.HandshakeResponse; import jakarta.websocket.server.ServerEndpointConfig; @@ -43,6 +45,7 @@ import org.apache.tomcat.websocket.Transformation; import org.apache.tomcat.websocket.TransformationFactory; import org.apache.tomcat.websocket.Util; import org.apache.tomcat.websocket.WsHandshakeResponse; +import org.apache.tomcat.websocket.pojo.PojoMethodMapping; public class UpgradeUtil { @@ -197,12 +200,31 @@ public class UpgradeUtil { resp.setHeader(Constants.WS_EXTENSIONS_HEADER_NAME, responseHeaderExtensions.toString()); } - WsHandshakeRequest wsRequest = new WsHandshakeRequest(req, pathParams); - WsHandshakeResponse wsResponse = new WsHandshakeResponse(); + // Add method mapping to user properties + if (!Endpoint.class.isAssignableFrom(sec.getEndpointClass()) && + sec.getUserProperties().get(org.apache.tomcat.websocket.pojo.Constants.POJO_METHOD_MAPPING_KEY) == null) { + // This is a POJO endpoint and the application has called upgrade + // directly. Need to add the method mapping. + try { + PojoMethodMapping methodMapping = new PojoMethodMapping(sec.getEndpointClass(), + sec.getDecoders(), sec.getPath(), sc.getInstanceManager(Thread.currentThread().getContextClassLoader())); + if (methodMapping.getOnClose() != null || methodMapping.getOnOpen() != null + || methodMapping.getOnError() != null || methodMapping.hasMessageHandlers()) { + sec.getUserProperties().put( + org.apache.tomcat.websocket.pojo.Constants.POJO_METHOD_MAPPING_KEY, methodMapping); + } + } catch (DeploymentException e) { + throw new ServletException( + sm.getString("upgradeUtil.pojoMpaFail", sec.getEndpointClass().getName()), e); + } + } + WsPerSessionServerEndpointConfig perSessionServerEndpointConfig = new WsPerSessionServerEndpointConfig(sec); - sec.getConfigurator().modifyHandshake(perSessionServerEndpointConfig, - wsRequest, wsResponse); + + WsHandshakeRequest wsRequest = new WsHandshakeRequest(req, pathParams); + WsHandshakeResponse wsResponse = new WsHandshakeResponse(); + sec.getConfigurator().modifyHandshake(perSessionServerEndpointConfig, wsRequest, wsResponse); wsRequest.finished(); // Add any additional headers diff --git a/java/org/apache/tomcat/websocket/server/WsServerContainer.java b/java/org/apache/tomcat/websocket/server/WsServerContainer.java index 135a1ba..0a29137 100644 --- a/java/org/apache/tomcat/websocket/server/WsServerContainer.java +++ b/java/org/apache/tomcat/websocket/server/WsServerContainer.java @@ -386,6 +386,17 @@ public class WsServerContainer extends WsWebSocketContainer * Overridden to make it visible to other classes in this package. */ @Override + protected InstanceManager getInstanceManager(ClassLoader classLoader) { + return super.getInstanceManager(classLoader); + } + + + /** + * {@inheritDoc} + * + * Overridden to make it visible to other classes in this package. + */ + @Override protected void registerSession(Object key, WsSession wsSession) { super.registerSession(key, wsSession); if (wsSession.isOpen() && diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 8a4de63..9e3f380 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -154,6 +154,11 @@ enable Tomcat to pass the WebSocket TCK but after updates to the TCK, it is no longer required. (markt) </fix> + <add> + Add support for POJO WebSocket endpoints to the programmatic upgrade + that allows applications to opt to upgrade an HTTP connection to + WebSocket. (markt) + </add> </changelog> </subsection> </section> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org