From af20af96266fca601f6f94276c0ae3f4f9fcb3fe Mon Sep 17 00:00:00 2001 From: Michel Jung Date: Sun, 7 Feb 2021 21:25:15 +0100 Subject: [PATCH 1/6] Use static `createInstanceFactory()` consistently --- .../java/io/undertow/websockets/jsr/EncodingFactory.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java index d20eb1b66..1acc466ef 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java @@ -163,7 +163,7 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp if (list == null) { binaryDecoders.put(type, list = new ArrayList<>()); } - list.add(classIntrospecter.createInstanceFactory(decoder)); + list.add(createInstanceFactory(classIntrospecter, decoder)); } catch (NoSuchMethodException e) { throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); } @@ -175,7 +175,7 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp if (list == null) { binaryDecoders.put(type, list = new ArrayList<>()); } - list.add(classIntrospecter.createInstanceFactory(decoder)); + list.add(createInstanceFactory(classIntrospecter, decoder)); } catch (NoSuchMethodException e) { throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); } @@ -187,7 +187,7 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp if (list == null) { textDecoders.put(type, list = new ArrayList<>()); } - list.add(classIntrospecter.createInstanceFactory(decoder)); + list.add(createInstanceFactory(classIntrospecter, decoder)); } catch (NoSuchMethodException e) { throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); } From a02927ff73dc7db80e21ab38916f0831e4fb7218 Mon Sep 17 00:00:00 2001 From: Michel Jung Date: Sun, 7 Feb 2021 21:25:53 +0100 Subject: [PATCH 2/6] Use Java 8 features in `EncodingFactory` --- .../websockets/jsr/EncodingFactory.java | 50 +++++-------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java index 1acc466ef..282f8a928 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java @@ -56,7 +56,7 @@ public class EncodingFactory { /** * An encoding factory that can deal with primitive types. */ - public static final EncodingFactory DEFAULT = new EncodingFactory(Collections.EMPTY_MAP, Collections.EMPTY_MAP, Collections.EMPTY_MAP, Collections.EMPTY_MAP); + public static final EncodingFactory DEFAULT = new EncodingFactory(Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap()); private final Map, List>> binaryEncoders; private final Map, List>> binaryDecoders; @@ -97,10 +97,10 @@ public boolean canDecodeBinary(final Class type) { public Encoding createEncoding(final EndpointConfig endpointConfig) { try { - Map, List>> binaryEncoders = this.binaryEncoders.isEmpty() ? Collections., List>>emptyMap() : new HashMap, List>>(); - Map, List>> binaryDecoders = this.binaryDecoders.isEmpty() ? Collections., List>>emptyMap() : new HashMap, List>>(); - Map, List>> textEncoders = this.textEncoders.isEmpty() ? Collections., List>>emptyMap() : new HashMap, List>>(); - Map, List>> textDecoders = this.textDecoders.isEmpty() ? Collections., List>>emptyMap() : new HashMap, List>>(); + Map, List>> binaryEncoders = this.binaryEncoders.isEmpty() ? Collections.emptyMap() : new HashMap<>(); + Map, List>> binaryDecoders = this.binaryDecoders.isEmpty() ? Collections.emptyMap() : new HashMap<>(); + Map, List>> textEncoders = this.textEncoders.isEmpty() ? Collections.emptyMap() : new HashMap<>(); + Map, List>> textDecoders = this.textDecoders.isEmpty() ? Collections.emptyMap() : new HashMap<>(); for (Map.Entry, List>> entry : this.binaryEncoders.entrySet()) { final List> val = new ArrayList<>(entry.getValue().size()); @@ -159,10 +159,7 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp try { Method method = decoder.getMethod("decode", ByteBuffer.class); final Class type = resolveReturnType(method, decoder); - List> list = binaryDecoders.get(type); - if (list == null) { - binaryDecoders.put(type, list = new ArrayList<>()); - } + List> list = binaryDecoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, decoder)); } catch (NoSuchMethodException e) { throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); @@ -171,10 +168,7 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp try { Method method = decoder.getMethod("decode", InputStream.class); final Class type = resolveReturnType(method, decoder); - List> list = binaryDecoders.get(type); - if (list == null) { - binaryDecoders.put(type, list = new ArrayList<>()); - } + List> list = binaryDecoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, decoder)); } catch (NoSuchMethodException e) { throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); @@ -183,10 +177,7 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp try { Method method = decoder.getMethod("decode", String.class); final Class type = resolveReturnType(method, decoder); - List> list = textDecoders.get(type); - if (list == null) { - textDecoders.put(type, list = new ArrayList<>()); - } + List> list = textDecoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, decoder)); } catch (NoSuchMethodException e) { throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); @@ -195,10 +186,7 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp try { Method method = decoder.getMethod("decode", Reader.class); final Class type = resolveReturnType(method, decoder); - List> list = textDecoders.get(type); - if (list == null) { - textDecoders.put(type, list = new ArrayList<>()); - } + List> list = textDecoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, decoder)); } catch (NoSuchMethodException e) { throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); @@ -211,31 +199,19 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp for (Class encoder : encoders) { if (Encoder.Binary.class.isAssignableFrom(encoder)) { final Class type = findEncodeMethod(encoder, ByteBuffer.class); - List> list = binaryEncoders.get(type); - if (list == null) { - binaryEncoders.put(type, list = new ArrayList<>()); - } + List> list = binaryEncoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, encoder)); } else if (Encoder.BinaryStream.class.isAssignableFrom(encoder)) { final Class type = findEncodeMethod(encoder, void.class, OutputStream.class); - List> list = binaryEncoders.get(type); - if (list == null) { - binaryEncoders.put(type, list = new ArrayList<>()); - } + List> list = binaryEncoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, encoder)); } else if (Encoder.Text.class.isAssignableFrom(encoder)) { final Class type = findEncodeMethod(encoder, String.class); - List> list = textEncoders.get(type); - if (list == null) { - textEncoders.put(type, list = new ArrayList<>()); - } + List> list = textEncoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, encoder)); } else if (Encoder.TextStream.class.isAssignableFrom(encoder)) { final Class type = findEncodeMethod(encoder, void.class, Writer.class); - List> list = textEncoders.get(type); - if (list == null) { - textEncoders.put(type, list = new ArrayList<>()); - } + List> list = textEncoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, encoder)); } } From 1c70ba84a4740b9e4d76740b9860b9ac9c0340f4 Mon Sep 17 00:00:00 2001 From: Michel Jung Date: Sun, 7 Feb 2021 22:04:33 +0100 Subject: [PATCH 3/6] Simplify createEncoding() Remove code duplication, reduce complexity. --- .../websockets/jsr/EncodingFactory.java | 79 +++++++++---------- 1 file changed, 38 insertions(+), 41 deletions(-) diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java index 282f8a928..09a2ddeec 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java @@ -96,49 +96,46 @@ public boolean canDecodeBinary(final Class type) { } public Encoding createEncoding(final EndpointConfig endpointConfig) { - try { - Map, List>> binaryEncoders = this.binaryEncoders.isEmpty() ? Collections.emptyMap() : new HashMap<>(); - Map, List>> binaryDecoders = this.binaryDecoders.isEmpty() ? Collections.emptyMap() : new HashMap<>(); - Map, List>> textEncoders = this.textEncoders.isEmpty() ? Collections.emptyMap() : new HashMap<>(); - Map, List>> textDecoders = this.textDecoders.isEmpty() ? Collections.emptyMap() : new HashMap<>(); + Map, List>> binaryEncoders = registerCoders(endpointConfig, this.binaryEncoders); + Map, List>> binaryDecoders = registerCoders(endpointConfig, this.binaryDecoders); + Map, List>> textEncoders = registerCoders(endpointConfig, this.textEncoders); + Map, List>> textDecoders = registerCoders(endpointConfig, this.textDecoders); + return new Encoding(binaryEncoders, binaryDecoders, textEncoders, textDecoders); + } - for (Map.Entry, List>> entry : this.binaryEncoders.entrySet()) { - final List> val = new ArrayList<>(entry.getValue().size()); - binaryEncoders.put(entry.getKey(), val); - for (InstanceFactory factory : entry.getValue()) { - InstanceHandle instance = factory.createInstance(); - instance.getInstance().init(endpointConfig); - val.add(instance); - } - } - for (Map.Entry, List>> entry : this.binaryDecoders.entrySet()) { - final List> val = new ArrayList<>(entry.getValue().size()); - binaryDecoders.put(entry.getKey(), val); - for (InstanceFactory factory : entry.getValue()) { - InstanceHandle instance = factory.createInstance(); - instance.getInstance().init(endpointConfig); - val.add(instance); - } - } - for (Map.Entry, List>> entry : this.textEncoders.entrySet()) { - final List> val = new ArrayList<>(entry.getValue().size()); - textEncoders.put(entry.getKey(), val); - for (InstanceFactory factory : entry.getValue()) { - InstanceHandle instance = factory.createInstance(); - instance.getInstance().init(endpointConfig); - val.add(instance); - } - } - for (Map.Entry, List>> entry : this.textDecoders.entrySet()) { - final List> val = new ArrayList<>(entry.getValue().size()); - textDecoders.put(entry.getKey(), val); - for (InstanceFactory factory : entry.getValue()) { - InstanceHandle instance = factory.createInstance(); - instance.getInstance().init(endpointConfig); - val.add(instance); - } + // Sacrifice some type checks to avoid generics-hell + @SuppressWarnings({"unchecked", "rawtypes"}) + private T registerCoders(EndpointConfig endpointConfig, Map coders) { + if (coders.isEmpty()) { + return (T) Collections.emptyMap(); + } + + Map result = new HashMap(); + for (Map.Entry, List>> entry : ((Map, List>>) coders).entrySet()) { + final List> val = new ArrayList<>(entry.getValue().size()); + result.put(entry.getKey(), val); + for (InstanceFactory factory : entry.getValue()) { + InstanceHandle instance = createInstance(factory); + initializeCoder(endpointConfig, instance); + val.add(instance); } - return new Encoding(binaryEncoders, binaryDecoders, textEncoders, textDecoders); + } + return (T) result; + } + + private void initializeCoder(EndpointConfig endpointConfig, InstanceHandle instance) { + if (instance.getInstance() instanceof Encoder) { + ((Encoder) instance.getInstance()).init(endpointConfig); + } else if (!(instance.getInstance() instanceof Decoder)) { + ((Decoder) instance.getInstance()).init(endpointConfig); + } else { + throw new IllegalStateException("Illegal type: " + ((Decoder) instance.getInstance()).getClass()); + } + } + + private static InstanceHandle createInstance(InstanceFactory factory) { + try { + return factory.createInstance(); } catch (InstantiationException e) { throw new RuntimeException(e); } From 13994d0284e15bf6c73ea2c90c0cb1caa1c98ecd Mon Sep 17 00:00:00 2001 From: Michel Jung Date: Sun, 7 Feb 2021 22:12:36 +0100 Subject: [PATCH 4/6] Allow classes to implement multiple encoders/decoders Fixes GH-50 --- .../websockets/jsr/EncodingFactory.java | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java index 09a2ddeec..f724b407d 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java @@ -152,6 +152,10 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp final Map, List>> textDecoders = new HashMap<>(); for (Class decoder : decoders) { + if (isUnknownDecoderSubclass(decoder)) { + throw JsrWebSocketMessages.MESSAGES.didNotImplementKnownDecoderSubclass(decoder); + } + if (Decoder.Binary.class.isAssignableFrom(decoder)) { try { Method method = decoder.getMethod("decode", ByteBuffer.class); @@ -161,7 +165,8 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp } catch (NoSuchMethodException e) { throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); } - } else if (Decoder.BinaryStream.class.isAssignableFrom(decoder)) { + } + if (Decoder.BinaryStream.class.isAssignableFrom(decoder)) { try { Method method = decoder.getMethod("decode", InputStream.class); final Class type = resolveReturnType(method, decoder); @@ -170,7 +175,8 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp } catch (NoSuchMethodException e) { throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); } - } else if (Decoder.Text.class.isAssignableFrom(decoder)) { + } + if (Decoder.Text.class.isAssignableFrom(decoder)) { try { Method method = decoder.getMethod("decode", String.class); final Class type = resolveReturnType(method, decoder); @@ -179,7 +185,8 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp } catch (NoSuchMethodException e) { throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); } - } else if (Decoder.TextStream.class.isAssignableFrom(decoder)) { + } + if (Decoder.TextStream.class.isAssignableFrom(decoder)) { try { Method method = decoder.getMethod("decode", Reader.class); final Class type = resolveReturnType(method, decoder); @@ -188,8 +195,6 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp } catch (NoSuchMethodException e) { throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); } - } else { - throw JsrWebSocketMessages.MESSAGES.didNotImplementKnownDecoderSubclass(decoder); } } @@ -198,15 +203,18 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp final Class type = findEncodeMethod(encoder, ByteBuffer.class); List> list = binaryEncoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, encoder)); - } else if (Encoder.BinaryStream.class.isAssignableFrom(encoder)) { + } + if (Encoder.BinaryStream.class.isAssignableFrom(encoder)) { final Class type = findEncodeMethod(encoder, void.class, OutputStream.class); List> list = binaryEncoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, encoder)); - } else if (Encoder.Text.class.isAssignableFrom(encoder)) { + } + if (Encoder.Text.class.isAssignableFrom(encoder)) { final Class type = findEncodeMethod(encoder, String.class); List> list = textEncoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, encoder)); - } else if (Encoder.TextStream.class.isAssignableFrom(encoder)) { + } + if (Encoder.TextStream.class.isAssignableFrom(encoder)) { final Class type = findEncodeMethod(encoder, void.class, Writer.class); List> list = textEncoders.computeIfAbsent(type, k -> new ArrayList<>()); list.add(createInstanceFactory(classIntrospecter, encoder)); @@ -215,6 +223,13 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp return new EncodingFactory(binaryEncoders, binaryDecoders, textEncoders, textDecoders); } + private static boolean isUnknownDecoderSubclass(Class decoder) { + return !Decoder.Binary.class.isAssignableFrom(decoder) + && !Decoder.BinaryStream.class.isAssignableFrom(decoder) + && !Decoder.Text.class.isAssignableFrom(decoder) + && !Decoder.TextStream.class.isAssignableFrom(decoder); + } + private static Class resolveReturnType(Method method, Class decoder) { Type genericReturnType = method.getGenericReturnType(); if (genericReturnType instanceof Class) { From cf03174a7fc5ee9e37730cd3acc45e6bc228d322 Mon Sep 17 00:00:00 2001 From: Michel Jung Date: Sun, 7 Feb 2021 22:23:29 +0100 Subject: [PATCH 5/6] Simplify createFactory() Remove code duplication, reduce complexity. --- .../websockets/jsr/EncodingFactory.java | 62 +++++++------------ 1 file changed, 22 insertions(+), 40 deletions(-) diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java index f724b407d..08c24118a 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java @@ -156,46 +156,10 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp throw JsrWebSocketMessages.MESSAGES.didNotImplementKnownDecoderSubclass(decoder); } - if (Decoder.Binary.class.isAssignableFrom(decoder)) { - try { - Method method = decoder.getMethod("decode", ByteBuffer.class); - final Class type = resolveReturnType(method, decoder); - List> list = binaryDecoders.computeIfAbsent(type, k -> new ArrayList<>()); - list.add(createInstanceFactory(classIntrospecter, decoder)); - } catch (NoSuchMethodException e) { - throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); - } - } - if (Decoder.BinaryStream.class.isAssignableFrom(decoder)) { - try { - Method method = decoder.getMethod("decode", InputStream.class); - final Class type = resolveReturnType(method, decoder); - List> list = binaryDecoders.computeIfAbsent(type, k -> new ArrayList<>()); - list.add(createInstanceFactory(classIntrospecter, decoder)); - } catch (NoSuchMethodException e) { - throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); - } - } - if (Decoder.Text.class.isAssignableFrom(decoder)) { - try { - Method method = decoder.getMethod("decode", String.class); - final Class type = resolveReturnType(method, decoder); - List> list = textDecoders.computeIfAbsent(type, k -> new ArrayList<>()); - list.add(createInstanceFactory(classIntrospecter, decoder)); - } catch (NoSuchMethodException e) { - throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); - } - } - if (Decoder.TextStream.class.isAssignableFrom(decoder)) { - try { - Method method = decoder.getMethod("decode", Reader.class); - final Class type = resolveReturnType(method, decoder); - List> list = textDecoders.computeIfAbsent(type, k -> new ArrayList<>()); - list.add(createInstanceFactory(classIntrospecter, decoder)); - } catch (NoSuchMethodException e) { - throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); - } - } + tryRegisterDecoder(classIntrospecter, binaryDecoders, decoder, Decoder.Binary.class, ByteBuffer.class); + tryRegisterDecoder(classIntrospecter, binaryDecoders, decoder, Decoder.BinaryStream.class, InputStream.class); + tryRegisterDecoder(classIntrospecter, textDecoders, decoder, Decoder.Text.class, String.class); + tryRegisterDecoder(classIntrospecter, textDecoders, decoder, Decoder.TextStream.class, Reader.class); } for (Class encoder : encoders) { @@ -230,6 +194,24 @@ private static boolean isUnknownDecoderSubclass(Class decoder && !Decoder.TextStream.class.isAssignableFrom(decoder); } + private static void tryRegisterDecoder(ClassIntrospecter classIntrospecter, Map, List>> binaryDecoders, Class decoder, Class decoderType, Class decodedType) throws DeploymentException { + if (!decoderType.isAssignableFrom(decoder)) { + return; + } + Method method = findDecodeMethod(decoder, decodedType); + final Class type = resolveReturnType(method, decoder); + List> list = binaryDecoders.computeIfAbsent(type, k -> new ArrayList<>()); + list.add(createInstanceFactory(classIntrospecter, decoder)); + } + + private static Method findDecodeMethod(Class decoder, Class type) throws DeploymentException { + try { + return decoder.getMethod("decode", type); + } catch (NoSuchMethodException e) { + throw JsrWebSocketMessages.MESSAGES.couldNotDetermineTypeOfDecodeMethodForClass(decoder, e); + } + } + private static Class resolveReturnType(Method method, Class decoder) { Type genericReturnType = method.getGenericReturnType(); if (genericReturnType instanceof Class) { From 89d8c5918468b00e246f6489457a991feecabba9 Mon Sep 17 00:00:00 2001 From: Michel Jung Date: Sun, 7 Feb 2021 22:32:36 +0100 Subject: [PATCH 6/6] Add error message 3043 didNotImplementKnownEncoderSubclass To be consistent with 3020 didNotImplementKnownDecoderSubclass --- .../io/undertow/websockets/jsr/EncodingFactory.java | 11 +++++++++++ .../undertow/websockets/jsr/JsrWebSocketMessages.java | 3 +++ 2 files changed, 14 insertions(+) diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java index 08c24118a..543876001 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/EncodingFactory.java @@ -163,6 +163,10 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp } for (Class encoder : encoders) { + if (isUnknownEncoderSubclass(encoder)) { + throw JsrWebSocketMessages.MESSAGES.didNotImplementKnownEncoderSubclass(encoder); + } + if (Encoder.Binary.class.isAssignableFrom(encoder)) { final Class type = findEncodeMethod(encoder, ByteBuffer.class); List> list = binaryEncoders.computeIfAbsent(type, k -> new ArrayList<>()); @@ -187,6 +191,13 @@ public static EncodingFactory createFactory(final ClassIntrospecter classIntrosp return new EncodingFactory(binaryEncoders, binaryDecoders, textEncoders, textDecoders); } + private static boolean isUnknownEncoderSubclass(Class encoder) { + return !Encoder.Binary.class.isAssignableFrom(encoder) + && !Encoder.BinaryStream.class.isAssignableFrom(encoder) + && !Encoder.Text.class.isAssignableFrom(encoder) + && !Encoder.TextStream.class.isAssignableFrom(encoder); + } + private static boolean isUnknownDecoderSubclass(Class decoder) { return !Decoder.Binary.class.isAssignableFrom(decoder) && !Decoder.BinaryStream.class.isAssignableFrom(decoder) diff --git a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/JsrWebSocketMessages.java b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/JsrWebSocketMessages.java index 6078b0959..3e71ec4e4 100644 --- a/websockets-jsr/src/main/java/io/undertow/websockets/jsr/JsrWebSocketMessages.java +++ b/websockets-jsr/src/main/java/io/undertow/websockets/jsr/JsrWebSocketMessages.java @@ -161,4 +161,7 @@ public interface JsrWebSocketMessages { @Message(id = 3042, value = "Deployment failed due to invalid programmatically added endpoints") RuntimeException deploymentFailedDueToProgramaticErrors(); + + @Message(id = 3043, value = "%s did not implement known decoder interface") + DeploymentException didNotImplementKnownEncoderSubclass(Class decoder); }