This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch websocket-userproperties-proxy in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit e61e9ad4ece051df45d4144c16c557a58b2a9286 Author: Mark Thomas <[email protected]> AuthorDate: Thu Mar 3 17:00:45 2022 +0000 First pass at implementing per session user properties using a proxy Compared to wrapping this has the benefit that the user can still cast their ServerEndpointConfig instance to the original implementation class and access implementation specfic methods. --- build.properties.default | 9 +++ build.xml | 22 ++++++ .../tomcat/websocket/server/UpgradeUtil.java | 21 +++++- .../server/WsPerSessionServerEndpointConfig.java | 84 ---------------------- .../WsPerSessionUserPropertiesMethodFilter.java | 29 ++++++++ .../WsPerSessionUserPropertiesMethodHandler.java | 42 +++++++++++ res/checkstyle/checkstyle.xml | 2 +- res/checkstyle/org-import-control.xml | 1 + 8 files changed, 123 insertions(+), 87 deletions(-) diff --git a/build.properties.default b/build.properties.default index d5bdf0e..773ba42 100644 --- a/build.properties.default +++ b/build.properties.default @@ -217,6 +217,15 @@ commons-daemon.native.src.loc.2=${base-commons.loc.2}/daemon/source/commons-daem commons-daemon.native.win.loc.1=${base-commons.loc.1}/daemon/binaries/windows/commons-daemon-${commons-daemon.version}-bin-windows.zip commons-daemon.native.win.loc.2=${base-commons.loc.2}/daemon/binaries/windows/commons-daemon-${commons-daemon.version}-bin-windows.zip +# ----- Javassist 3.28.0-GA or later ----- +javassist.version=3.28.0-GA +javassist.checksum.enabled=true +javassist.checksum.algorithm=MD5|SHA-1 +javassist.checksum.value=1a2dd8c76321cef26cc2669fe70a2557|9a958811a88381bb159cc2f5ed79c34a45c4af7a +javassist.home=${base.path}/javassist-${javassist.version} +javassist.jar=${javassist.home}/javassist-${javassist.version}.jar +javassist.loc=${base-maven.loc}/org/javassist/javassist/${javassist.version}/javassist-${javassist.version}.jar + # ----- JUnit Unit Test Suite, version 4.11 or later ----- junit.version=4.13.2 junit.checksum.enabled=true diff --git a/build.xml b/build.xml index fb5c56a..a448531 100644 --- a/build.xml +++ b/build.xml @@ -220,6 +220,7 @@ <pathelement location="${jaxrpc-lib.jar}"/> <pathelement location="${wsdl4j-lib.jar}"/> <pathelement location="${migration-lib.jar}"/> + <pathelement location="${javassist.jar}"/> </path> <path id="tomcat.classpath"> @@ -1492,6 +1493,17 @@ </delete> <copy file="${migration-lib.jar}" todir="${tomcat.build}/lib"/> + <!-- Delete all other versions of Javassist and copy the current one --> + <local name="javassist.jar.filename" /> + <basename property="javassist.jar.filename" file="${javassist.jar}"/> + <delete verbose="true"> + <fileset dir="${tomcat.build}/lib"> + <include name="javassist-*.jar"/> + <exclude name="${javassist.jar.filename}"/> + </fileset> + </delete> + <copy file="${javassist.jar}" todir="${tomcat.build}/lib"/> + <!-- Delete all other versions of OpenSSL support for Tomcat and copy the current one --> <!-- After module release <local name="openssl-lib.jar.filename" /> @@ -3162,6 +3174,16 @@ skip.installer property in build.properties" /> <param name="checksum.value" value="${migration-lib.checksum.value}"/> </antcall> + <!-- Javassist --> + <antcall target="downloadfile"> + <param name="sourcefile" value="${javassist.loc}"/> + <param name="destfile" value="${javassist.jar}"/> + <param name="destdir" value="${javassist.home}"/> + <param name="checksum.enabled" value="${javassist.checksum.enabled}"/> + <param name="checksum.algorithm" value="${javassist.checksum.algorithm}"/> + <param name="checksum.value" value="${javassist.checksum.value}"/> + </antcall> + </target> <target name="download-test-compile" diff --git a/java/org/apache/tomcat/websocket/server/UpgradeUtil.java b/java/org/apache/tomcat/websocket/server/UpgradeUtil.java index de6c352..9b96334 100644 --- a/java/org/apache/tomcat/websocket/server/UpgradeUtil.java +++ b/java/org/apache/tomcat/websocket/server/UpgradeUtil.java @@ -17,6 +17,7 @@ package org.apache.tomcat.websocket.server; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; @@ -37,6 +38,9 @@ import jakarta.websocket.Extension; import jakarta.websocket.HandshakeResponse; import jakarta.websocket.server.ServerEndpointConfig; +import javassist.util.proxy.MethodFilter; +import javassist.util.proxy.ProxyFactory; + import org.apache.tomcat.util.codec.binary.Base64; import org.apache.tomcat.util.res.StringManager; import org.apache.tomcat.util.security.ConcurrentMessageDigest; @@ -54,6 +58,8 @@ public class UpgradeUtil { private static final byte[] WS_ACCEPT = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11".getBytes( StandardCharsets.ISO_8859_1); + private static final MethodFilter PER_SESSION_USER_PROPERTIES_METHOD_FILTER = + new WsPerSessionUserPropertiesMethodFilter(); private UpgradeUtil() { // Utility class. Hide default constructor. @@ -219,8 +225,19 @@ public class UpgradeUtil { } } - WsPerSessionServerEndpointConfig perSessionServerEndpointConfig = - new WsPerSessionServerEndpointConfig(sec); + ProxyFactory factory = new ProxyFactory(); + factory.setSuperclass(sec.getClass()); + factory.setFilter(PER_SESSION_USER_PROPERTIES_METHOD_FILTER); + + ServerEndpointConfig perSessionServerEndpointConfig; + try { + perSessionServerEndpointConfig = (ServerEndpointConfig) factory.create( + new Class<?>[0], new Object[0], new WsPerSessionUserPropertiesMethodHandler(sec)); + } catch (NoSuchMethodException | IllegalArgumentException | InstantiationException | IllegalAccessException + | InvocationTargetException e) { + // Should never happen + throw new IllegalStateException(e); + } WsHandshakeRequest wsRequest = new WsHandshakeRequest(req, pathParams); WsHandshakeResponse wsResponse = new WsHandshakeResponse(); diff --git a/java/org/apache/tomcat/websocket/server/WsPerSessionServerEndpointConfig.java b/java/org/apache/tomcat/websocket/server/WsPerSessionServerEndpointConfig.java deleted file mode 100644 index 07452e9..0000000 --- a/java/org/apache/tomcat/websocket/server/WsPerSessionServerEndpointConfig.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.tomcat.websocket.server; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import jakarta.websocket.Decoder; -import jakarta.websocket.Encoder; -import jakarta.websocket.Extension; -import jakarta.websocket.server.ServerEndpointConfig; - -/** - * Wraps the provided {@link ServerEndpointConfig} and provides a per session - * view - the difference being that the map returned by {@link - * #getUserProperties()} is unique to this instance rather than shared with the - * wrapped {@link ServerEndpointConfig}. - */ -class WsPerSessionServerEndpointConfig implements ServerEndpointConfig { - - private final ServerEndpointConfig perEndpointConfig; - private final Map<String,Object> perSessionUserProperties = - new ConcurrentHashMap<>(); - - WsPerSessionServerEndpointConfig(ServerEndpointConfig perEndpointConfig) { - this.perEndpointConfig = perEndpointConfig; - perSessionUserProperties.putAll(perEndpointConfig.getUserProperties()); - } - - @Override - public List<Class<? extends Encoder>> getEncoders() { - return perEndpointConfig.getEncoders(); - } - - @Override - public List<Class<? extends Decoder>> getDecoders() { - return perEndpointConfig.getDecoders(); - } - - @Override - public Map<String,Object> getUserProperties() { - return perSessionUserProperties; - } - - @Override - public Class<?> getEndpointClass() { - return perEndpointConfig.getEndpointClass(); - } - - @Override - public String getPath() { - return perEndpointConfig.getPath(); - } - - @Override - public List<String> getSubprotocols() { - return perEndpointConfig.getSubprotocols(); - } - - @Override - public List<Extension> getExtensions() { - return perEndpointConfig.getExtensions(); - } - - @Override - public Configurator getConfigurator() { - return perEndpointConfig.getConfigurator(); - } -} diff --git a/java/org/apache/tomcat/websocket/server/WsPerSessionUserPropertiesMethodFilter.java b/java/org/apache/tomcat/websocket/server/WsPerSessionUserPropertiesMethodFilter.java new file mode 100644 index 0000000..991ca17 --- /dev/null +++ b/java/org/apache/tomcat/websocket/server/WsPerSessionUserPropertiesMethodFilter.java @@ -0,0 +1,29 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.websocket.server; + +import java.lang.reflect.Method; + +import javassist.util.proxy.MethodFilter; + +public class WsPerSessionUserPropertiesMethodFilter implements MethodFilter { + + @Override + public boolean isHandled(Method method) { + return method.getName().equals("getUserProperties") & method.getParameterCount() == 0; + } +} diff --git a/java/org/apache/tomcat/websocket/server/WsPerSessionUserPropertiesMethodHandler.java b/java/org/apache/tomcat/websocket/server/WsPerSessionUserPropertiesMethodHandler.java new file mode 100644 index 0000000..76f0d0c --- /dev/null +++ b/java/org/apache/tomcat/websocket/server/WsPerSessionUserPropertiesMethodHandler.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.websocket.server; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import jakarta.websocket.server.ServerEndpointConfig; + +import javassist.util.proxy.MethodHandler; + +public class WsPerSessionUserPropertiesMethodHandler implements MethodHandler { + + private final Map<String,Object> perSessionUserProperties = new ConcurrentHashMap<>(); + + + public WsPerSessionUserPropertiesMethodHandler(ServerEndpointConfig perEndpointConfig) { + perSessionUserProperties.putAll(perEndpointConfig.getUserProperties()); + } + + + @Override + public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable { + return perSessionUserProperties; + } + +} diff --git a/res/checkstyle/checkstyle.xml b/res/checkstyle/checkstyle.xml index ed16bc3..3aa631e 100644 --- a/res/checkstyle/checkstyle.xml +++ b/res/checkstyle/checkstyle.xml @@ -69,7 +69,7 @@ <property name="illegalPkgs" value="sun,junit.framework"/> </module> <module name="ImportOrder"> - <property name="groups" value="java,javax,jakarta,org.hamcrest,org.junit,org,async,jsp2,util"/> + <property name="groups" value="java,javax,jakarta,javassist,org.hamcrest,org.junit,org,async,jsp2,util"/> <property name="ordered" value="true"/> <property name="separated" value="true"/> <property name="option" value="above"/> diff --git a/res/checkstyle/org-import-control.xml b/res/checkstyle/org-import-control.xml index 29ea88f..3320e38 100644 --- a/res/checkstyle/org-import-control.xml +++ b/res/checkstyle/org-import-control.xml @@ -188,6 +188,7 @@ <allow pkg="jakarta.servlet"/> <allow pkg="org.apache.coyote.http11.upgrade"/> <allow pkg="org.apache.tomcat.websocket"/> + <allow pkg="javassist.util.proxy"/> </subpackage> </subpackage> </subpackage> --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
