From a1333786a9daa797a62516849f8a67ae48de5d0e Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Mon, 15 Aug 2016 13:32:05 -0700 Subject: [PATCH] Issue #207 - Support javax.websocket version 1.1 # Conflicts: # jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderFactoryTest.java # jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderFactoryTest.java # jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageHandlerFactoryTest.java # jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdDecoderTest.java # jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/PrimitiveDecoderMetadataSetTest.java # jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/metadata/DecoderMetadataSetTest.java # jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/metadata/EncoderMetadataSetTest.java --- .../jetty/websocket/jsr356/JsrSession.java | 30 +- .../jsr356/decoders/AvailableDecoders.java | 109 ++- .../jsr356/encoders/AvailableEncoders.java | 2 + .../jsr356/function/JsrEndpointFunctions.java | 760 +++++++++++------- .../messages/DecodedBinaryMessageSink.java | 9 +- .../DecodedInputStreamMessageSink.java | 7 +- .../messages/DecodedReaderMessageSink.java | 8 +- .../messages/DecodedTextMessageSink.java | 9 +- .../websocket/jsr356/DecoderFactoryTest.java | 112 --- .../websocket/jsr356/EncoderFactoryTest.java | 91 --- .../jetty/websocket/jsr356/EncoderTest.java | 1 + .../websocket/jsr356/JsrSessionTest.java | 32 +- .../jsr356/MessageHandlerFactoryTest.java | 81 -- .../annotations/JsrParamIdDecoderTest.java | 47 -- .../decoders/AvailableDecodersTest.java | 64 +- .../PrimitiveDecoderMetadataSetTest.java | 54 -- .../encoders/AvailableEncodersTest.java | 70 +- ...srEndpointFunctions_BadSignaturesTest.java | 20 +- .../JsrEndpointFunctions_OnCloseTest.java | 18 +- .../JsrEndpointFunctions_OnErrorTest.java | 16 +- ...ndpointFunctions_OnMessage_BinaryTest.java | 28 +- ...rEndpointFunctions_OnMessage_TextTest.java | 31 +- .../JsrEndpointFunctions_OnOpenTest.java | 18 +- .../metadata/DecoderMetadataSetTest.java | 134 --- .../metadata/EncoderMetadataSetTest.java | 134 --- .../function/CommonEndpointFunctions.java | 35 + 26 files changed, 813 insertions(+), 1107 deletions(-) delete mode 100644 jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderFactoryTest.java delete mode 100644 jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderFactoryTest.java delete mode 100644 jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageHandlerFactoryTest.java delete mode 100644 jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdDecoderTest.java delete mode 100644 jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/PrimitiveDecoderMetadataSetTest.java delete mode 100644 jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/metadata/DecoderMetadataSetTest.java delete mode 100644 jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/metadata/EncoderMetadataSetTest.java diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSession.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSession.java index 427d7a889ab..a8fd192cba1 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSession.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JsrSession.java @@ -118,7 +118,7 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess } getJsrEndpointFunctions().setMessageHandler(clazz, handler); - messageHandlerSet.add(handler); + registerMessageHandler(handler); } /** @@ -135,7 +135,7 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess LOG.debug("MessageHandler.Whole class: {}", handler.getClass()); } getJsrEndpointFunctions().setMessageHandler(clazz, handler); - messageHandlerSet.add(handler); + registerMessageHandler(handler); } /** @@ -149,21 +149,36 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess { Objects.requireNonNull(handler, "MessageHandler cannot be null"); Class handlerClass = handler.getClass(); + boolean added = false; if (MessageHandler.Whole.class.isAssignableFrom(handlerClass)) { Class onMessageClass = ReflectUtils.findGenericClassFor(handlerClass, MessageHandler.Whole.class); addMessageHandler(onMessageClass, (MessageHandler.Whole) handler); + added = true; } if (MessageHandler.Partial.class.isAssignableFrom(handlerClass)) { Class onMessageClass = ReflectUtils.findGenericClassFor(handlerClass, MessageHandler.Partial.class); addMessageHandler(onMessageClass, (MessageHandler.Partial) handler); + added = true; } - // Should not be possible - throw new IllegalStateException("Not a recognized " + MessageHandler.class.getName() + " type: " + handler.getClass()); + if (!added) + { + // Should not be possible + throw new IllegalStateException("Not a recognized " + MessageHandler.class.getName() + " type: " + handler.getClass()); + } + } + + protected synchronized void registerMessageHandler(MessageHandler handler) + { + if (messageHandlerSet == null) + { + messageHandlerSet = new HashSet<>(); + } + messageHandlerSet.add(handler); } @Override @@ -240,6 +255,11 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess @Override public Set getMessageHandlers() { + if (messageHandlerSet == null) + { + return Collections.emptySet(); + } + // Always return copy of set, as it is common to iterate and remove from the real set. return new HashSet(messageHandlerSet); } @@ -304,7 +324,7 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess @Override public synchronized void removeMessageHandler(MessageHandler handler) { - if (messageHandlerSet.remove(handler)) + if (messageHandlerSet != null && messageHandlerSet.remove(handler)) { // remove from endpoint functions too getJsrEndpointFunctions().removeMessageHandler(handler); diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/AvailableDecoders.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/AvailableDecoders.java index 22992de09fd..e439a39dd3f 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/AvailableDecoders.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/AvailableDecoders.java @@ -42,13 +42,20 @@ public class AvailableDecoders implements Predicate> public final Class decoder; public final Class interfaceType; public final Class objectType; + public final boolean primitive; public Decoder instance; public RegisteredDecoder(Class decoder, Class interfaceType, Class objectType) + { + this(decoder, interfaceType, objectType, false); + } + + public RegisteredDecoder(Class decoder, Class interfaceType, Class objectType, boolean primitive) { this.decoder = decoder; this.interfaceType = interfaceType; this.objectType = objectType; + this.primitive = primitive; } public boolean implementsInterface(Class type) @@ -61,7 +68,7 @@ public class AvailableDecoders implements Predicate> return objectType.isAssignableFrom(type); } } - + private final EndpointConfig config; private LinkedList registeredDecoders; @@ -71,36 +78,36 @@ public class AvailableDecoders implements Predicate> registeredDecoders = new LinkedList<>(); // TEXT based [via Class reference] - register(BooleanDecoder.class, Decoder.Text.class, Boolean.class); - register(ByteDecoder.class, Decoder.Text.class, Byte.class); - register(CharacterDecoder.class, Decoder.Text.class, Character.class); - register(DoubleDecoder.class, Decoder.Text.class, Double.class); - register(FloatDecoder.class, Decoder.Text.class, Float.class); - register(IntegerDecoder.class, Decoder.Text.class, Integer.class); - register(LongDecoder.class, Decoder.Text.class, Long.class); - register(StringDecoder.class, Decoder.Text.class, String.class); + registerPrimitive(BooleanDecoder.class, Decoder.Text.class, Boolean.class); + registerPrimitive(ByteDecoder.class, Decoder.Text.class, Byte.class); + registerPrimitive(CharacterDecoder.class, Decoder.Text.class, Character.class); + registerPrimitive(DoubleDecoder.class, Decoder.Text.class, Double.class); + registerPrimitive(FloatDecoder.class, Decoder.Text.class, Float.class); + registerPrimitive(IntegerDecoder.class, Decoder.Text.class, Integer.class); + registerPrimitive(LongDecoder.class, Decoder.Text.class, Long.class); + registerPrimitive(StringDecoder.class, Decoder.Text.class, String.class); // TEXT based [via Primitive reference] - register(BooleanDecoder.class, Decoder.Text.class, Boolean.TYPE); - register(ByteDecoder.class, Decoder.Text.class, Byte.TYPE); - register(CharacterDecoder.class, Decoder.Text.class, Character.TYPE); - register(DoubleDecoder.class, Decoder.Text.class, Double.TYPE); - register(FloatDecoder.class, Decoder.Text.class, Float.TYPE); - register(IntegerDecoder.class, Decoder.Text.class, Integer.TYPE); - register(LongDecoder.class, Decoder.Text.class, Long.TYPE); + registerPrimitive(BooleanDecoder.class, Decoder.Text.class, Boolean.TYPE); + registerPrimitive(ByteDecoder.class, Decoder.Text.class, Byte.TYPE); + registerPrimitive(CharacterDecoder.class, Decoder.Text.class, Character.TYPE); + registerPrimitive(DoubleDecoder.class, Decoder.Text.class, Double.TYPE); + registerPrimitive(FloatDecoder.class, Decoder.Text.class, Float.TYPE); + registerPrimitive(IntegerDecoder.class, Decoder.Text.class, Integer.TYPE); + registerPrimitive(LongDecoder.class, Decoder.Text.class, Long.TYPE); // BINARY based - register(ByteBufferDecoder.class, Decoder.Binary.class, ByteBuffer.class); - register(ByteArrayDecoder.class, Decoder.Binary.class, byte[].class); + registerPrimitive(ByteBufferDecoder.class, Decoder.Binary.class, ByteBuffer.class); + registerPrimitive(ByteArrayDecoder.class, Decoder.Binary.class, byte[].class); // STREAMING based - register(ReaderDecoder.class, Decoder.TextStream.class, Reader.class); - register(InputStreamDecoder.class, Decoder.BinaryStream.class, InputStreamDecoder.class); + registerPrimitive(ReaderDecoder.class, Decoder.TextStream.class, Reader.class); + registerPrimitive(InputStreamDecoder.class, Decoder.BinaryStream.class, InputStreamDecoder.class); } - private void register(Class decoderClass, Class interfaceType, Class type) + private void registerPrimitive(Class decoderClass, Class interfaceType, Class type) { - registeredDecoders.add(new RegisteredDecoder(decoderClass, interfaceType, type)); + registeredDecoders.add(new RegisteredDecoder(decoderClass, interfaceType, type, true)); } public void register(Class decoder) @@ -167,14 +174,34 @@ public class AvailableDecoders implements Predicate> if (objectType == null) { StringBuilder err = new StringBuilder(); - err.append("Invalid Decoder Object type declared for interface "); + err.append("Unknown Decoder Object type declared for interface "); err.append(interfaceClass.getName()); err.append(" on class "); err.append(decoder); throw new InvalidWebSocketException(err.toString()); } - registeredDecoders.add(new RegisteredDecoder(decoder, interfaceClass, objectType)); + try + { + RegisteredDecoder conflicts = registeredDecoders.stream() + .filter(registered -> registered.isType(objectType)) + .filter(registered -> !registered.primitive) + .findFirst() + .get(); + + StringBuilder err = new StringBuilder(); + err.append("Duplicate Decoder Object type "); + err.append(objectType.getName()); + err.append(" in "); + err.append(decoder.getName()); + err.append(", previously declared in "); + err.append(conflicts.decoder.getName()); + throw new InvalidWebSocketException(err.toString()); + } + catch (NoSuchElementException e) + { + registeredDecoders.addFirst(new RegisteredDecoder(decoder, interfaceClass, objectType)); + } } public List supporting(Class interfaceType) @@ -204,28 +231,36 @@ public class AvailableDecoders implements Predicate> } } - public Decoder getInstanceFor(Class type) + public T getInstanceOf(RegisteredDecoder registeredDecoder) + { + if (registeredDecoder.instance != null) + { + return (T) registeredDecoder.instance; + } + + try + { + registeredDecoder.instance = registeredDecoder.decoder.newInstance(); + registeredDecoder.instance.init(this.config); + return (T) registeredDecoder.instance; + } + catch (InstantiationException | IllegalAccessException e) + { + throw new InitException("Unable to init Decoder for type:" + registeredDecoder.decoder.getName(), e); + } + } + + public T getInstanceFor(Class type) { try { RegisteredDecoder registeredDecoder = getRegisteredDecoderFor(type); - if (registeredDecoder.instance != null) - { - return registeredDecoder.instance; - } - - registeredDecoder.instance = registeredDecoder.decoder.newInstance(); - registeredDecoder.instance.init(this.config); - return registeredDecoder.instance; + return getInstanceOf(registeredDecoder); } catch (NoSuchElementException e) { throw new InvalidWebSocketException("No Decoder found for type " + type); } - catch (InstantiationException | IllegalAccessException e) - { - throw new InitException("Unable to init Decoder for type:" + type.getName(), e); - } } public static Object decodePrimitive(String value, Class type) throws DecodeException diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/encoders/AvailableEncoders.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/encoders/AvailableEncoders.java index f354e6c2969..107be796496 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/encoders/AvailableEncoders.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/encoders/AvailableEncoders.java @@ -22,6 +22,7 @@ import java.nio.ByteBuffer; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -65,6 +66,7 @@ public class AvailableEncoders implements Predicate> public AvailableEncoders(EndpointConfig config) { + Objects.requireNonNull(config); this.config = config; registeredEncoders = new LinkedList<>(); diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java index 568738af4bb..b23c9328a05 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions.java @@ -27,8 +27,10 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.concurrent.Executor; import java.util.function.BiFunction; +import java.util.function.Function; import java.util.stream.Collectors; import javax.websocket.ClientEndpoint; @@ -55,6 +57,7 @@ import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.common.InvalidSignatureException; import org.eclipse.jetty.websocket.common.function.CommonEndpointFunctions; +import org.eclipse.jetty.websocket.common.message.MessageSink; import org.eclipse.jetty.websocket.common.message.PartialBinaryMessageSink; import org.eclipse.jetty.websocket.common.message.PartialTextMessageSink; import org.eclipse.jetty.websocket.common.reflect.Arg; @@ -78,6 +81,42 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions { private static final Logger LOG = Log.getLogger(JsrEndpointFunctions.class); + protected static class MessageHandlerPongFunction implements Function + { + public final MessageHandler messageHandler; + public final Function function; + + public MessageHandlerPongFunction(MessageHandler messageHandler, Function function) + { + this.messageHandler = messageHandler; + this.function = function; + } + + @Override + public Void apply(ByteBuffer byteBuffer) + { + return function.apply(byteBuffer); + } + } + + protected static class MessageHandlerSink implements MessageSink + { + public final MessageHandler messageHandler; + public final MessageSink delegateSink; + + public MessageHandlerSink(MessageHandler messageHandler, MessageSink messageSink) + { + this.messageHandler = messageHandler; + this.delegateSink = messageSink; + } + + @Override + public void accept(ByteBuffer payload, Boolean fin) + { + this.delegateSink.accept(payload, fin); + } + } + /** * Represents a static value (as seen from a URI PathParam) *

@@ -128,6 +167,212 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions } } + public AvailableDecoders getAvailableDecoders() + { + return decoders; + } + + /** + * Identify the message sink the handler belongs to and remove it. + * Block if the message sink is actively being used. + * + * @param handler the handler to remove from possible message sinks + * @see {@link javax.websocket.Session#removeMessageHandler(MessageHandler)} + * @since JSR356 v1.0 + */ + public void removeMessageHandler(MessageHandler handler) + { + Function pongFunction = getOnPongFunction(); + if (pongFunction instanceof MessageHandlerPongFunction) + { + MessageHandlerPongFunction handlerFunction = (MessageHandlerPongFunction) pongFunction; + if (handlerFunction.messageHandler == handler) + clearOnPongFunction(); + } + + MessageSink textSink = getOnTextSink(); + if (textSink instanceof MessageHandlerSink) + { + MessageHandlerSink handlerSink = (MessageHandlerSink) textSink; + if (handlerSink.messageHandler == handler) + clearOnTextSink(); + } + + MessageSink binarySink = getOnBinarySink(); + if (binarySink instanceof MessageHandlerSink) + { + MessageHandlerSink handlerSink = (MessageHandlerSink) binarySink; + if (handlerSink.messageHandler == handler) + clearOnBinarySink(); + } + } + + /** + * Create a message sink from the provided partial message handler. + * + * @param clazz the object type + * @param handler the partial message handler + * @param the generic defined type + * @throws IllegalStateException if unable to process message handler + * @see {@link javax.websocket.Session#addMessageHandler(Class, MessageHandler.Partial)} + * @since JSR356 v1.1 + */ + public void setMessageHandler(Class clazz, MessageHandler.Partial handler) throws IllegalStateException + { + if (String.class.isAssignableFrom(clazz)) + { + PartialTextMessageSink sink = new PartialTextMessageSink((partial) -> + { + handler.onMessage((T) partial.getPayload(), partial.isFin()); + return null; + }); + setOnText(new MessageHandlerSink(handler, sink), handler); + return; + } + + if (ByteBuffer.class.isAssignableFrom(clazz)) + { + PartialBinaryMessageSink sink = new PartialBinaryMessageSink((partial) -> + { + handler.onMessage((T) partial.getPayload(), partial.isFin()); + return null; + }); + setOnBinary(new MessageHandlerSink(handler, sink), handler); + return; + } + + if (byte[].class.isAssignableFrom(clazz)) + { + PartialBinaryMessageSink sink = new PartialBinaryMessageSink((partial) -> + { + handler.onMessage((T) BufferUtil.toArray(partial.getPayload()), partial.isFin()); + return null; + }); + setOnBinary(new MessageHandlerSink(handler, sink), handler); + return; + } + + // If we reached this point, then the Partial type is unrecognized + StringBuilder err = new StringBuilder(); + err.append("Unrecognized ").append(MessageHandler.Partial.class.getName()); + err.append(" type <"); + err.append(clazz.getName()); + err.append("> on "); + err.append(handler.getClass().getName()); + throw new IllegalStateException(err.toString()); + } + + /** + * Create a message sink from the provided whole message handler. + * + * @param clazz the object type + * @param handler the whole message handler + * @param the generic defined type + * @throws IllegalStateException if unable to process message handler + * @see {@link javax.websocket.Session#addMessageHandler(Class, MessageHandler.Whole)} + * @since JSR356 v1.1 + */ + public void setMessageHandler(Class clazz, MessageHandler.Whole handler) throws IllegalStateException + { + try + { + // Is this a PongMessage? + if (PongMessage.class.isAssignableFrom(PongMessage.class)) + { + Function pongFunction = (payload) -> + { + handler.onMessage((T) new JsrPongMessage(payload)); + return null; + }; + setOnPong(new MessageHandlerPongFunction(handler, pongFunction), handler); + return; + } + + // Try to determine TEXT / BINARY + AvailableDecoders.RegisteredDecoder registeredDecoder = decoders.getRegisteredDecoderFor(clazz); + + if (registeredDecoder.implementsInterface(Decoder.Text.class)) + { + Decoder.Text decoderInstance = decoders.getInstanceOf(registeredDecoder); + DecodedTextMessageSink textSink = new DecodedTextMessageSink( + policy, this, decoderInstance, + (msg) -> + { + handler.onMessage((T) msg); + return null; + } + ); + setOnText(new MessageHandlerSink(handler, textSink), handler); + return; + } + + if (registeredDecoder.implementsInterface(Decoder.Binary.class)) + { + Decoder.Binary decoderInstance = decoders.getInstanceOf(registeredDecoder); + DecodedBinaryMessageSink binarySink = new DecodedBinaryMessageSink( + policy, this, decoderInstance, + (msg) -> + { + handler.onMessage((T) msg); + return null; + } + ); + setOnBinary(new MessageHandlerSink(handler, binarySink), handler); + return; + } + + if (registeredDecoder.implementsInterface(Decoder.TextStream.class)) + { + Decoder.TextStream decoderInstance = decoders.getInstanceOf(registeredDecoder); + DecodedReaderMessageSink textSink = new DecodedReaderMessageSink( + this, decoderInstance, + (msg) -> + { + handler.onMessage((T) msg); + return null; + } + ); + setOnText(new MessageHandlerSink(handler, textSink), handler); + return; + } + + if (registeredDecoder.implementsInterface(Decoder.BinaryStream.class)) + { + Decoder.BinaryStream decoderInstance = decoders.getInstanceOf(registeredDecoder); + DecodedInputStreamMessageSink binarySink = new DecodedInputStreamMessageSink( + this, decoderInstance, + (msg) -> + { + handler.onMessage((T) msg); + return null; + } + ); + setOnBinary(new MessageHandlerSink(handler, binarySink), handler); + return; + } + + // If we reached this point, then the Whole Message Type is unrecognized + StringBuilder err = new StringBuilder(); + err.append("Unrecognized message type "); + err.append(MessageHandler.Whole.class.getName()); + err.append("<").append(clazz.getName()); + err.append("> on "); + err.append(handler.getClass().getName()); + throw new IllegalStateException(err.toString()); + } + catch (NoSuchElementException e) + { + // No valid decoder for type found + StringBuilder err = new StringBuilder(); + err.append("Not a valid ").append(MessageHandler.Whole.class.getName()); + err.append(" type <"); + err.append(clazz.getName()); + err.append("> on "); + err.append(handler.getClass().getName()); + throw new IllegalStateException(err.toString()); + } + } + @Override protected void discoverEndpointFunctions(Object endpoint) { @@ -296,228 +541,21 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions onmsgloop: for (Method onMsg : onMessages) { - boolean foundMatch = false; + // Whole TEXT / Binary Message + if (discoverOnMessageWholeText(onMsg)) continue onmsgloop; + if (discoverOnMessageWholeBinary(onMsg)) continue onmsgloop; - // Try to determine Message type (BINARY / TEXT) from signature + // Partial TEXT / BINARY + if (discoverOnMessagePartialText(onMsg)) continue onmsgloop; + if (discoverOnMessagePartialBinaryArray(onMsg)) continue onmsgloop; + if (discoverOnMessagePartialBinaryBuffer(onMsg)) continue onmsgloop; - Arg SESSION = new Arg(Session.class); + // Streaming TEXT / BINARY + if (discoverOnMessageTextStream(onMsg)) continue onmsgloop; + if (discoverOnMessageBinaryStream(onMsg)) continue onmsgloop; - // -------------------- - // -- Whole Messages -- - // -------------------- - - // Whole TEXT - for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.Text.class)) - { - UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); - if (sig.test(onMsg)) - { - assertOnMessageSignature(onMsg); - - final Object[] args = newCallArgs(sig.getCallArgs()); - args[0] = getSession(); - BiFunction invoker = sig.newFunction(onMsg); - Decoder.Text decoderInstance = getDecoderInstance(decoder, Decoder.Text.class); - DecodedTextMessageSink textSink = new DecodedTextMessageSink( - getSession(), - decoderInstance, - (msg) -> - { - args[1] = msg; - return invoker.apply(endpoint, args); - } - ); - setOnText(textSink, onMsg); - continue onmsgloop; - } - } - - // Whole BINARY - for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.Binary.class)) - { - UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); - if (sig.test(onMsg)) - { - assertOnMessageSignature(onMsg); - - final Object[] args = newCallArgs(sig.getCallArgs()); - args[0] = getSession(); - BiFunction invoker = sig.newFunction(onMsg); - Decoder.Binary decoderInstance = getDecoderInstance(decoder, Decoder.Binary.class); - DecodedBinaryMessageSink binarySink = new DecodedBinaryMessageSink( - getSession(), - decoderInstance, - (msg) -> - { - args[1] = msg; - return invoker.apply(endpoint, args); - } - ); - setOnBinary(binarySink, onMsg); - continue onmsgloop; - } - } - - // ---------------------- - // -- Partial Messages -- - // ---------------------- - - Arg ARG_PARTIAL_BOOL = new Arg(boolean.class).required(); - - // Partial Text - Arg ARG_STRING = new Arg(String.class).required(); - UnorderedSignature sigPartialText = new UnorderedSignature(createCallArgs(SESSION, ARG_STRING, ARG_PARTIAL_BOOL)); - if (sigPartialText.test(onMsg)) - { - // Found partial text args - assertOnMessageSignature(onMsg); - - final Object[] args = newCallArgs(sigPartialText.getCallArgs()); - args[0] = getSession(); - BiFunction invoker = sigPartialText.newFunction(onMsg); - // No decoders for Partial messages per JSR-356 (PFD1 spec) - setOnText(new PartialTextMessageSink((partial) -> - { - args[1] = partial.getPayload(); - args[2] = partial.isFin(); - invoker.apply(endpoint, args); - return null; - }), onMsg); - continue onmsgloop; - } - - // Partial Binary - Arg ARG_BYTE_ARRAY = new Arg(byte[].class).required(); - UnorderedSignature sigPartialBinaryArray = new UnorderedSignature(createCallArgs(SESSION, ARG_BYTE_ARRAY, ARG_PARTIAL_BOOL)); - if (sigPartialBinaryArray.test(onMsg)) - { - // Found partial binary array args - assertOnMessageSignature(onMsg); - - final Object[] args = newCallArgs(sigPartialBinaryArray.getCallArgs()); - args[0] = getSession(); - BiFunction invoker = sigPartialBinaryArray.newFunction(onMsg); - // No decoders for Partial messages per JSR-356 (PFD1 spec) - setOnBinary(new PartialBinaryMessageSink((partial) -> - { - args[1] = BufferUtil.toArray(partial.getPayload()); - args[2] = partial.isFin(); - invoker.apply(endpoint, args); - return null; - }), onMsg); - continue onmsgloop; - } - - Arg ARG_BYTE_BUFFER = new Arg(ByteBuffer.class).required(); - UnorderedSignature sigPartialByteBuffer = new UnorderedSignature(createCallArgs(SESSION, ARG_BYTE_BUFFER, ARG_PARTIAL_BOOL)); - if (sigPartialByteBuffer.test(onMsg)) - { - // Found partial binary array args - assertOnMessageSignature(onMsg); - - final Object[] args = newCallArgs(sigPartialBinaryArray.getCallArgs()); - args[0] = getSession(); - BiFunction invoker = sigPartialBinaryArray.newFunction(onMsg); - // No decoders for Partial messages per JSR-356 (PFD1 spec) - setOnBinary(new PartialBinaryMessageSink((partial) -> - { - args[1] = partial.getPayload(); - args[2] = partial.isFin(); - invoker.apply(endpoint, args); - return null; - }), onMsg); - continue onmsgloop; - } - - // ------------------------ - // -- Streaming Messages -- - // ------------------------ - - // Streaming TEXT --- - for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.TextStream.class)) - { - UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); - if (sig.test(onMsg)) - { - assertOnMessageSignature(onMsg); - - final Object[] args = newCallArgs(sig.getCallArgs()); - args[0] = getSession(); - BiFunction invoker = sig.newFunction(onMsg); - Decoder.TextStream decoderInstance = getDecoderInstance(decoder, Decoder.TextStream.class); - DecodedReaderMessageSink textSink = new DecodedReaderMessageSink( - getSession(), - decoderInstance, - (msg) -> - { - args[1] = msg; - return invoker.apply(endpoint, args); - } - ); - setOnText(textSink, onMsg); - continue onmsgloop; - } - } - - // Streaming BINARY --- - for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.BinaryStream.class)) - { - UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); - if (sig.test(onMsg)) - { - assertOnMessageSignature(onMsg); - - final Object[] args = newCallArgs(sig.getCallArgs()); - args[0] = getSession(); - BiFunction invoker = sig.newFunction(onMsg); - Decoder.BinaryStream decoderInstance = getDecoderInstance(decoder, Decoder.BinaryStream.class); - DecodedInputStreamMessageSink textSink = new DecodedInputStreamMessageSink( - getSession(), - decoderInstance, - (msg) -> - { - args[1] = msg; - return invoker.apply(endpoint, args); - } - ); - setOnText(textSink, onMsg); - continue onmsgloop; - } - } - - // ------------------- - // -- Pong Messages -- - // ------------------- - - // Test for PONG - UnorderedSignature sigPong = new UnorderedSignature(createCallArgs(SESSION, new Arg(PongMessage.class).required())); - if (sigPong.test(onMsg)) - { - assertOnMessageSignature(onMsg); - - final Object[] args = newCallArgs(sigPong.getCallArgs()); - args[0] = getSession(); - BiFunction invoker = sigPong.newFunction(onMsg); - // No decoder for PongMessage - setOnPing((pong) -> - { - args[1] = new JsrPongMessage(pong); - Object ret = invoker.apply(endpoint, args); - if (ret != null) - { - try - { - getSession().getBasicRemote().sendObject(ret); - } - catch (EncodeException | IOException e) - { - throw new WebSocketException(e); - } - } - return null; - }, onMsg); - continue onmsgloop; - } + // PONG + if (discoverOnMessagePong(onMsg)) continue onmsgloop; // If we reached this point, then we have a @OnMessage annotated method // that doesn't match any known signature above. @@ -527,58 +565,243 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions } } - /** - * Create a message sink from the provided partial message handler. - * - * @param clazz the object type - * @param handler the partial message handler - * @param the generic defined type - * @see {@link javax.websocket.Session#addMessageHandler(Class, MessageHandler.Partial)} - */ - public void setMessageHandler(Class clazz, MessageHandler.Partial handler) + private boolean discoverOnMessagePong(Method onMsg) throws DecodeException { - // TODO: implement - } - - /** - * Create a message sink from the provided whole message handler. - * - * @param clazz the object type - * @param handler the whole message handler - * @param the generic defined type - * @see {@link javax.websocket.Session#addMessageHandler(Class, MessageHandler.Whole)} - */ - public void setMessageHandler(Class clazz, MessageHandler.Whole handler) - { - // TODO: implement - } - - /** - * Identify the message sink the handler belongs to and remove it. - * Block if the message sink is actively being used. - * @param handler the handler to remove from possible message sinks - * @see {@link javax.websocket.Session#removeMessageHandler(MessageHandler)} - */ - public void removeMessageHandler(MessageHandler handler) - { - // TODO: implement - } - - private T getDecoderInstance(AvailableDecoders.RegisteredDecoder registeredDecoder, Class interfaceType) - { - // TODO: Return previous instantiated decoders here - - Class decoderClass = registeredDecoder.decoder; - try + Arg SESSION = new Arg(Session.class); + UnorderedSignature sigPong = new UnorderedSignature(createCallArgs(SESSION, new Arg(PongMessage.class).required())); + if (sigPong.test(onMsg)) { - Decoder decoder = decoderClass.newInstance(); - decoder.init(this.endpointConfig); - return (T) decoder; + assertOnMessageSignature(onMsg); + + final Object[] args = newCallArgs(sigPong.getCallArgs()); + BiFunction invoker = sigPong.newFunction(onMsg); + // No decoder for PongMessage + setOnPong((pong) -> + { + args[0] = getSession(); + args[1] = new JsrPongMessage(pong); + Object ret = invoker.apply(endpoint, args); + if (ret != null) + { + try + { + getSession().getBasicRemote().sendObject(ret); + } + catch (EncodeException | IOException e) + { + throw new WebSocketException(e); + } + } + return null; + }, onMsg); + return true; } - catch (Throwable t) + return false; + } + + private boolean discoverOnMessageBinaryStream(Method onMsg) throws DecodeException + { + Arg SESSION = new Arg(Session.class); + for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.BinaryStream.class)) { - throw new InvalidWebSocketException("Unable to initialize required Decoder: " + decoderClass.getName(), t); + UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); + if (sig.test(onMsg)) + { + assertOnMessageSignature(onMsg); + + final Object[] args = newCallArgs(sig.getCallArgs()); + BiFunction invoker = sig.newFunction(onMsg); + Decoder.BinaryStream decoderInstance = decoders.getInstanceOf(decoder); + DecodedInputStreamMessageSink streamSink = new DecodedInputStreamMessageSink( + this, + decoderInstance, + (msg) -> + { + args[0] = getSession(); + args[1] = msg; + return invoker.apply(endpoint, args); + } + ); + setOnBinary(streamSink, onMsg); + return true; + } } + return false; + } + + private boolean discoverOnMessageTextStream(Method onMsg) throws DecodeException + { + Arg SESSION = new Arg(Session.class); + for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.TextStream.class)) + { + UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); + if (sig.test(onMsg)) + { + assertOnMessageSignature(onMsg); + + final Object[] args = newCallArgs(sig.getCallArgs()); + BiFunction invoker = sig.newFunction(onMsg); + Decoder.TextStream decoderInstance = decoders.getInstanceOf(decoder); + DecodedReaderMessageSink streamSink = new DecodedReaderMessageSink( + this, + decoderInstance, + (msg) -> + { + args[0] = getSession(); + args[1] = msg; + return invoker.apply(endpoint, args); + } + ); + setOnText(streamSink, onMsg); + return true; + } + } + return false; + } + + @SuppressWarnings("Duplicates") + private boolean discoverOnMessagePartialBinaryBuffer(Method onMsg) throws DecodeException + { + Arg SESSION = new Arg(Session.class); + Arg ARG_BYTE_BUFFER = new Arg(ByteBuffer.class).required(); + Arg ARG_PARTIAL_BOOL = new Arg(boolean.class).required(); + UnorderedSignature sigPartialByteBuffer = new UnorderedSignature(createCallArgs(SESSION, ARG_BYTE_BUFFER, ARG_PARTIAL_BOOL)); + if (sigPartialByteBuffer.test(onMsg)) + { + // Found partial binary array args + assertOnMessageSignature(onMsg); + + final Object[] args = newCallArgs(sigPartialByteBuffer.getCallArgs()); + BiFunction invoker = sigPartialByteBuffer.newFunction(onMsg); + // No decoders for Partial messages per JSR-356 (PFD1 spec) + setOnBinary(new PartialBinaryMessageSink((partial) -> + { + args[0] = getSession(); + args[1] = partial.getPayload(); + args[2] = partial.isFin(); + invoker.apply(endpoint, args); + return null; + }), onMsg); + return true; + } + return false; + } + + private boolean discoverOnMessagePartialBinaryArray(Method onMsg) throws DecodeException + { + Arg SESSION = new Arg(Session.class); + Arg ARG_BYTE_ARRAY = new Arg(byte[].class).required(); + Arg ARG_PARTIAL_BOOL = new Arg(boolean.class).required(); + UnorderedSignature sigPartialBinaryArray = new UnorderedSignature(createCallArgs(SESSION, ARG_BYTE_ARRAY, ARG_PARTIAL_BOOL)); + if (sigPartialBinaryArray.test(onMsg)) + { + // Found partial binary array args + assertOnMessageSignature(onMsg); + + final Object[] args = newCallArgs(sigPartialBinaryArray.getCallArgs()); + BiFunction invoker = sigPartialBinaryArray.newFunction(onMsg); + // No decoders for Partial messages per JSR-356 (PFD1 spec) + setOnBinary(new PartialBinaryMessageSink((partial) -> + { + args[0] = getSession(); + args[1] = BufferUtil.toArray(partial.getPayload()); + args[2] = partial.isFin(); + invoker.apply(endpoint, args); + return null; + }), onMsg); + return true; + } + return false; + } + + @SuppressWarnings("Duplicates") + private boolean discoverOnMessagePartialText(Method onMsg) throws DecodeException + { + Arg SESSION = new Arg(Session.class); + Arg ARG_PARTIAL_BOOL = new Arg(boolean.class).required(); + Arg ARG_STRING = new Arg(String.class).required(); + UnorderedSignature sigPartialText = new UnorderedSignature(createCallArgs(SESSION, ARG_STRING, ARG_PARTIAL_BOOL)); + if (sigPartialText.test(onMsg)) + { + // Found partial text args + assertOnMessageSignature(onMsg); + + final Object[] args = newCallArgs(sigPartialText.getCallArgs()); + BiFunction invoker = sigPartialText.newFunction(onMsg); + // No decoders for Partial messages per JSR-356 (PFD1 spec) + setOnText(new PartialTextMessageSink((partial) -> + { + args[0] = getSession(); + args[1] = partial.getPayload(); + args[2] = partial.isFin(); + invoker.apply(endpoint, args); + return null; + }), onMsg); + return true; + } + return false; + } + + private boolean discoverOnMessageWholeBinary(Method onMsg) throws DecodeException + { + Arg SESSION = new Arg(Session.class); + for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.Binary.class)) + { + UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); + if (sig.test(onMsg)) + { + assertOnMessageSignature(onMsg); + + final Object[] args = newCallArgs(sig.getCallArgs()); + BiFunction invoker = sig.newFunction(onMsg); + Decoder.Binary decoderInstance = decoders.getInstanceOf(decoder); + DecodedBinaryMessageSink binarySink = new DecodedBinaryMessageSink( + policy, + this, + decoderInstance, + (msg) -> + { + args[0] = getSession(); + args[1] = msg; + return invoker.apply(endpoint, args); + } + ); + setOnBinary(binarySink, onMsg); + return true; + } + } + return false; + } + + private boolean discoverOnMessageWholeText(Method onMsg) throws DecodeException + { + Arg SESSION = new Arg(Session.class); + for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.Text.class)) + { + UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); + if (sig.test(onMsg)) + { + assertOnMessageSignature(onMsg); + + final Object[] args = newCallArgs(sig.getCallArgs()); + BiFunction invoker = sig.newFunction(onMsg); + Decoder.Text decoderInstance = decoders.getInstanceOf(decoder); + DecodedTextMessageSink textSink = new DecodedTextMessageSink( + policy, + this, + decoderInstance, + (msg) -> + { + args[0] = getSession(); + args[1] = msg; + return invoker.apply(endpoint, args); + } + ); + setOnText(textSink, onMsg); + return true; + } + } + return false; } private void assertSignatureValid(DynamicArgs.Signature sig, Class annotationClass, Method method) @@ -631,11 +854,6 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions } } - public AvailableDecoders getAvailableDecoders() - { - return decoders; - } - protected Object[] newCallArgs(Arg[] callArgs) throws DecodeException { int len = callArgs.length; diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedBinaryMessageSink.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedBinaryMessageSink.java index d9f7a9225b1..065e73c7bd3 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedBinaryMessageSink.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedBinaryMessageSink.java @@ -26,14 +26,15 @@ import javax.websocket.Decoder; import javax.websocket.EncodeException; import org.eclipse.jetty.websocket.api.WebSocketException; +import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.common.message.ByteBufferMessageSink; -import org.eclipse.jetty.websocket.jsr356.JsrSession; +import org.eclipse.jetty.websocket.jsr356.function.JsrEndpointFunctions; public class DecodedBinaryMessageSink extends ByteBufferMessageSink { - public DecodedBinaryMessageSink(JsrSession session, Decoder.Binary decoder, Function onMessageFunction) + public DecodedBinaryMessageSink(WebSocketPolicy policy, JsrEndpointFunctions endpointFunctions, Decoder.Binary decoder, Function onMessageFunction) { - super(session.getPolicy(), (byteBuf) -> + super(policy, (byteBuf) -> { try { @@ -47,7 +48,7 @@ public class DecodedBinaryMessageSink extends ByteBufferMessageSink if (ret != null) { // send response - session.getBasicRemote().sendObject(ret); + endpointFunctions.getSession().getBasicRemote().sendObject(ret); } return null; diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedInputStreamMessageSink.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedInputStreamMessageSink.java index cc92e9f8c9f..944fbc071db 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedInputStreamMessageSink.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedInputStreamMessageSink.java @@ -28,14 +28,15 @@ import javax.websocket.EncodeException; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.common.message.InputStreamMessageSink; import org.eclipse.jetty.websocket.jsr356.JsrSession; +import org.eclipse.jetty.websocket.jsr356.function.JsrEndpointFunctions; public class DecodedInputStreamMessageSink extends InputStreamMessageSink { - public DecodedInputStreamMessageSink(JsrSession session, + public DecodedInputStreamMessageSink(JsrEndpointFunctions endpointFunctions, Decoder.BinaryStream decoder, Function onMessageFunction) { - super(session.getExecutor(), (reader) -> + super(endpointFunctions.getExecutor(), (reader) -> { try { @@ -47,7 +48,7 @@ public class DecodedInputStreamMessageSink extends InputStreamMessageSink if (ret != null) { // send response - session.getBasicRemote().sendObject(ret); + endpointFunctions.getSession().getBasicRemote().sendObject(ret); } return null; diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedReaderMessageSink.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedReaderMessageSink.java index 8d5bf0713bc..fd3efb1e174 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedReaderMessageSink.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedReaderMessageSink.java @@ -27,13 +27,13 @@ import javax.websocket.EncodeException; import org.eclipse.jetty.websocket.api.WebSocketException; import org.eclipse.jetty.websocket.common.message.ReaderMessageSink; -import org.eclipse.jetty.websocket.jsr356.JsrSession; +import org.eclipse.jetty.websocket.jsr356.function.JsrEndpointFunctions; public class DecodedReaderMessageSink extends ReaderMessageSink { - public DecodedReaderMessageSink(JsrSession session, Decoder.TextStream decoder, Function onMessageFunction) + public DecodedReaderMessageSink(JsrEndpointFunctions endpointFunctions, Decoder.TextStream decoder, Function onMessageFunction) { - super(session.getExecutor(), (reader) -> + super(endpointFunctions.getExecutor(), (reader) -> { try { @@ -45,7 +45,7 @@ public class DecodedReaderMessageSink extends ReaderMessageSink if (ret != null) { // send response - session.getBasicRemote().sendObject(ret); + endpointFunctions.getSession().getBasicRemote().sendObject(ret); } return null; diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedTextMessageSink.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedTextMessageSink.java index 4474384e3b2..ce2fefd7ca3 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedTextMessageSink.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/DecodedTextMessageSink.java @@ -26,14 +26,15 @@ import javax.websocket.Decoder; import javax.websocket.EncodeException; import org.eclipse.jetty.websocket.api.WebSocketException; +import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.common.message.StringMessageSink; -import org.eclipse.jetty.websocket.jsr356.JsrSession; +import org.eclipse.jetty.websocket.jsr356.function.JsrEndpointFunctions; public class DecodedTextMessageSink extends StringMessageSink { - public DecodedTextMessageSink(JsrSession session, Decoder.Text decoder, Function onMessageFunction) + public DecodedTextMessageSink(WebSocketPolicy policy, JsrEndpointFunctions endpointFunctions, Decoder.Text decoder, Function onMessageFunction) { - super(session.getPolicy(), (message) -> + super(policy, (message) -> { try { @@ -45,7 +46,7 @@ public class DecodedTextMessageSink extends StringMessageSink if (ret != null) { // send response - session.getBasicRemote().sendObject(ret); + endpointFunctions.getSession().getBasicRemote().sendObject(ret); } return null; diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderFactoryTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderFactoryTest.java deleted file mode 100644 index f0f26572970..00000000000 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderFactoryTest.java +++ /dev/null @@ -1,112 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.jsr356; - -import static org.hamcrest.Matchers.is; - -import java.nio.ByteBuffer; -import java.util.Date; - -import javax.websocket.Decoder; - -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; -import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; -import org.eclipse.jetty.websocket.jsr356.decoders.ByteArrayDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.ByteBufferDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.DateDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.IntegerDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.LongDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.PrimitiveDecoderMetadataSet; -import org.eclipse.jetty.websocket.jsr356.decoders.StringDecoder; -import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadata; -import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadataSet; -import org.eclipse.jetty.websocket.jsr356.samples.Fruit; -import org.eclipse.jetty.websocket.jsr356.samples.FruitDecoder; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class DecoderFactoryTest -{ - private DecoderMetadataSet metadatas; - private DecoderFactory factory; - - private void assertMetadataFor(Class type, Class expectedDecoderClass, MessageType expectedType) - { - DecoderMetadata metadata = factory.getMetadataFor(type); - Assert.assertEquals("metadata.coderClass",metadata.getCoderClass(),expectedDecoderClass); - Assert.assertThat("metadata.messageType",metadata.getMessageType(),is(expectedType)); - Assert.assertEquals("metadata.objectType",metadata.getObjectType(),type); - } - - @Before - public void initDecoderFactory() - { - WebSocketContainerScope containerScope = new SimpleContainerScope(WebSocketPolicy.newClientPolicy()); - - DecoderFactory primitivesFactory = new DecoderFactory(containerScope,PrimitiveDecoderMetadataSet.INSTANCE); - metadatas = new DecoderMetadataSet(); - factory = new DecoderFactory(containerScope,metadatas,primitivesFactory); - } - - @Test - public void testGetMetadataForByteArray() - { - assertMetadataFor(byte[].class,ByteArrayDecoder.class,MessageType.BINARY); - } - - @Test - public void testGetMetadataForByteBuffer() - { - assertMetadataFor(ByteBuffer.class,ByteBufferDecoder.class,MessageType.BINARY); - } - - @Test - public void testGetMetadataForDate() - { - metadatas.add(DateDecoder.class); - assertMetadataFor(Date.class,DateDecoder.class,MessageType.TEXT); - } - - @Test - public void testGetMetadataForFruit() - { - metadatas.add(FruitDecoder.class); - assertMetadataFor(Fruit.class,FruitDecoder.class,MessageType.TEXT); - } - - @Test - public void testGetMetadataForInteger() - { - assertMetadataFor(Integer.TYPE,IntegerDecoder.class,MessageType.TEXT); - } - - @Test - public void testGetMetadataForLong() - { - assertMetadataFor(Long.TYPE,LongDecoder.class,MessageType.TEXT); - } - - @Test - public void testGetStringDecoder() - { - assertMetadataFor(String.class,StringDecoder.class,MessageType.TEXT); - } -} diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderFactoryTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderFactoryTest.java deleted file mode 100644 index 2e9d79160df..00000000000 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderFactoryTest.java +++ /dev/null @@ -1,91 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.jsr356; - -import static org.hamcrest.Matchers.is; - -import javax.websocket.Encoder; - -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; -import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; -import org.eclipse.jetty.websocket.jsr356.encoders.IntegerEncoder; -import org.eclipse.jetty.websocket.jsr356.encoders.LongEncoder; -import org.eclipse.jetty.websocket.jsr356.encoders.PrimitiveEncoderMetadataSet; -import org.eclipse.jetty.websocket.jsr356.metadata.EncoderMetadata; -import org.eclipse.jetty.websocket.jsr356.metadata.EncoderMetadataSet; -import org.eclipse.jetty.websocket.jsr356.samples.Fruit; -import org.eclipse.jetty.websocket.jsr356.samples.FruitBinaryEncoder; -import org.eclipse.jetty.websocket.jsr356.samples.FruitTextEncoder; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -/** - * Tests against the AvailableEncoders class - */ -public class EncoderFactoryTest -{ - private EncoderMetadataSet metadatas; - private EncoderFactory factory; - - private void assertMetadataFor(Class type, Class expectedEncoderClass, MessageType expectedType) - { - EncoderMetadata metadata = factory.getMetadataFor(type); - Assert.assertEquals("metadata.coderClass",metadata.getCoderClass(),expectedEncoderClass); - Assert.assertThat("metadata.messageType",metadata.getMessageType(),is(expectedType)); - Assert.assertEquals("metadata.objectType",metadata.getObjectType(),type); - } - - @Before - public void initEncoderFactory() - { - WebSocketContainerScope containerScope = new SimpleContainerScope(WebSocketPolicy.newClientPolicy()); - - EncoderFactory primitivesFactory = new EncoderFactory(containerScope,PrimitiveEncoderMetadataSet.INSTANCE); - metadatas = new EncoderMetadataSet(); - factory = new EncoderFactory(containerScope,metadatas,primitivesFactory); - } - - @Test - public void testGetMetadataForFruitBinary() - { - metadatas.add(FruitBinaryEncoder.class); - assertMetadataFor(Fruit.class,FruitBinaryEncoder.class,MessageType.BINARY); - } - - @Test - public void testGetMetadataForFruitText() - { - metadatas.add(FruitTextEncoder.class); - assertMetadataFor(Fruit.class,FruitTextEncoder.class,MessageType.TEXT); - } - - @Test - public void testGetMetadataForInteger() - { - assertMetadataFor(Integer.TYPE,IntegerEncoder.class,MessageType.TEXT); - } - - @Test - public void testGetMetadataForLong() - { - assertMetadataFor(Long.TYPE,LongEncoder.class,MessageType.TEXT); - } -} diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java index ae95501c319..13b10640f60 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java @@ -206,6 +206,7 @@ public class EncoderTest } } + @SuppressWarnings("Duplicates") private Quotes getQuotes(String filename) throws IOException { Quotes quotes = new Quotes(); diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/JsrSessionTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/JsrSessionTest.java index eb353486c38..e4e5602b742 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/JsrSessionTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/JsrSessionTest.java @@ -27,7 +27,6 @@ import javax.websocket.MessageHandler; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.common.test.DummyConnection; import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig; -import org.eclipse.jetty.websocket.jsr356.client.SimpleEndpointMetadata; import org.eclipse.jetty.websocket.jsr356.handlers.ByteArrayWholeHandler; import org.eclipse.jetty.websocket.jsr356.handlers.ByteBufferPartialHandler; import org.eclipse.jetty.websocket.jsr356.handlers.LongMessageHandler; @@ -44,29 +43,19 @@ public class JsrSessionTest @Before public void initSession() { - container = new ClientContainer(); String id = JsrSessionTest.class.getSimpleName(); URI requestURI = URI.create("ws://localhost/" + id); WebSocketPolicy policy = WebSocketPolicy.newClientPolicy(); + DummyConnection connection = new DummyConnection(policy); ClientEndpointConfig config = new EmptyClientEndpointConfig(); - DummyEndpoint websocket = new DummyEndpoint(); - SimpleEndpointMetadata metadata = new SimpleEndpointMetadata(websocket.getClass()); - // Executor executor = null; - - ConfiguredEndpoint ei = new ConfiguredEndpoint(websocket,config); - -// EventDriver driver = new JsrEndpointEventDriver(policy,ei); - DummyConnection connection = new DummyConnection(); - session = new JsrSession(container,id,requestURI,ei,connection); + ConfiguredEndpoint ei = new ConfiguredEndpoint(new DummyEndpoint(), config); + session = new JsrSession(container, id, requestURI, ei, connection); } @Test public void testMessageHandlerBinary() throws DeploymentException { session.addMessageHandler(new ByteBufferPartialHandler()); -// MessageHandlerWrapper wrapper = session.getMessageHandlerWrapper(MessageType.BINARY); -// Assert.assertThat("Binary Handler",wrapper.getHandler(),instanceOf(ByteBufferPartialHandler.class)); -// Assert.assertEquals("Message Class",wrapper.getMetadata().getMessageClass(),ByteBuffer.class); } @Test @@ -74,12 +63,6 @@ public class JsrSessionTest { session.addMessageHandler(new StringWholeHandler()); session.addMessageHandler(new ByteArrayWholeHandler()); -// MessageHandlerWrapper wrapper = session.getMessageHandlerWrapper(MessageType.TEXT); -// Assert.assertThat("Text Handler",wrapper.getHandler(),instanceOf(StringWholeHandler.class)); -// Assert.assertEquals("Message Class",wrapper.getMetadata().getMessageClass(),String.class); -// wrapper = session.getMessageHandlerWrapper(MessageType.BINARY); -// Assert.assertThat("Binary Handler",wrapper.getHandler(),instanceOf(ByteArrayWholeHandler.class)); -// Assert.assertEquals("Message Class",wrapper.getMetadata().getMessageClass(),byte[].class); } @Test @@ -90,20 +73,11 @@ public class JsrSessionTest session.addMessageHandler(new ByteArrayWholeHandler()); // add BINARY handler session.removeMessageHandler(oldText); // remove original TEXT handler session.addMessageHandler(new LongMessageHandler()); // add new TEXT handler -// MessageHandlerWrapper wrapper = session.getMessageHandlerWrapper(MessageType.BINARY); -// Assert.assertThat("Binary Handler",wrapper.getHandler(),instanceOf(ByteArrayWholeHandler.class)); -// Assert.assertEquals("Message Class",wrapper.getMetadata().getMessageClass(),byte[].class); -// wrapper = session.getMessageHandlerWrapper(MessageType.TEXT); -// Assert.assertThat("Text Handler",wrapper.getHandler(),instanceOf(LongMessageHandler.class)); -// Assert.assertEquals("Message Class",wrapper.getMetadata().getMessageClass(),Long.class); } @Test public void testMessageHandlerText() throws DeploymentException { session.addMessageHandler(new StringWholeHandler()); -// MessageHandlerWrapper wrapper = session.getMessageHandlerWrapper(MessageType.TEXT); -// Assert.assertThat("Text Handler",wrapper.getHandler(),instanceOf(StringWholeHandler.class)); -// Assert.assertEquals("Message Class",wrapper.getMetadata().getMessageClass(),String.class); } } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageHandlerFactoryTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageHandlerFactoryTest.java deleted file mode 100644 index 7fef3895c57..00000000000 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageHandlerFactoryTest.java +++ /dev/null @@ -1,81 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.jsr356; - -import static org.hamcrest.Matchers.is; - -import java.lang.reflect.Type; -import java.util.List; - -import javax.websocket.DeploymentException; - -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; -import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; -import org.eclipse.jetty.websocket.jsr356.decoders.PrimitiveDecoderMetadataSet; -import org.eclipse.jetty.websocket.jsr356.handlers.ByteArrayPartialHandler; -import org.eclipse.jetty.websocket.jsr356.handlers.StringPartialHandler; -import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadata; -import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadataSet; -import org.eclipse.jetty.websocket.jsr356.metadata.MessageHandlerMetadata; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -public class MessageHandlerFactoryTest -{ - private MessageHandlerFactory factory; - private DecoderMetadataSet metadatas; - private DecoderFactory decoders; - - @Before - public void init() throws DeploymentException - { - WebSocketContainerScope containerScope = new SimpleContainerScope(WebSocketPolicy.newClientPolicy()); - - DecoderFactory primitivesFactory = new DecoderFactory(containerScope,PrimitiveDecoderMetadataSet.INSTANCE); - metadatas = new DecoderMetadataSet(); - decoders = new DecoderFactory(containerScope,metadatas,primitivesFactory); - factory = new MessageHandlerFactory(); - } - - @Test - public void testByteArrayPartial() throws DeploymentException - { - List metadatas = factory.getMetadata(ByteArrayPartialHandler.class); - Assert.assertThat("Metadata.list.size",metadatas.size(),is(1)); - - MessageHandlerMetadata handlerMetadata = metadatas.get(0); - DecoderMetadata decoderMetadata = decoders.getMetadataFor(handlerMetadata.getMessageClass()); - Assert.assertThat("Message Type",decoderMetadata.getMessageType(),is(MessageType.BINARY)); - Assert.assertThat("Message Class",handlerMetadata.getMessageClass(),is((Type)byte[].class)); - } - - @Test - public void testStringPartial() throws DeploymentException - { - List metadatas = factory.getMetadata(StringPartialHandler.class); - Assert.assertThat("Metadata.list.size",metadatas.size(),is(1)); - - MessageHandlerMetadata handlerMetadata = metadatas.get(0); - DecoderMetadata decoderMetadata = decoders.getMetadataFor(handlerMetadata.getMessageClass()); - Assert.assertThat("Message Type",decoderMetadata.getMessageType(),is(MessageType.TEXT)); - Assert.assertThat("Message Class",handlerMetadata.getMessageClass(),is((Type)String.class)); - } -} diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdDecoderTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdDecoderTest.java deleted file mode 100644 index fa923e3085b..00000000000 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdDecoderTest.java +++ /dev/null @@ -1,47 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.jsr356.annotations; - -@Deprecated -public class JsrParamIdDecoderTest -{ - /*private JsrCallable getOnMessageCallableFrom(Class clazz, String methodName) - { - for (Method method : clazz.getMethods()) - { - if (method.getName().equals(methodName)) - { - return new OnMessageCallable(clazz,method); - } - } - return null; - } - - @Test - public void testMatchDateDecoder() - { - DecoderMetadata metadata = new DecoderMetadata(DateDecoder.class,Date.class,MessageType.TEXT,false); - JsrParamIdDecoder paramId = new JsrParamIdDecoder(metadata); - - JsrCallable callable = getOnMessageCallableFrom(DateTextSocket.class,"onMessage"); - Param param = new Param(0,Date.class,null); - - Assert.assertThat("Match for Decoder",paramId.process(param,callable),is(true)); - }*/ -} diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/AvailableDecodersTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/AvailableDecodersTest.java index 5d705278e5e..55b1ff205a6 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/AvailableDecodersTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/AvailableDecodersTest.java @@ -18,6 +18,7 @@ package org.eclipse.jetty.websocket.jsr356.decoders; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; @@ -33,10 +34,13 @@ import javax.websocket.DecodeException; import javax.websocket.Decoder; import javax.websocket.EndpointConfig; +import org.eclipse.jetty.websocket.api.InvalidWebSocketException; import org.eclipse.jetty.websocket.common.util.Hex; import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class AvailableDecodersTest { @@ -47,30 +51,25 @@ public class AvailableDecodersTest { testConfig = new EmptyClientEndpointConfig(); } - - private AvailableDecoders decoders = new AvailableDecoders(); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private AvailableDecoders decoders = new AvailableDecoders(testConfig); private void assertTextDecoder(Class type, String value, T expectedDecoded) throws IllegalAccessException, InstantiationException, DecodeException { - Class decoderClass = decoders.getDecoderFor(type); - assertThat("Decoder Class", decoderClass, notNullValue()); - - Decoder.Text decoder = (Decoder.Text) decoderClass.newInstance(); - decoder.init(testConfig); + Decoder.Text decoder = (Decoder.Text) decoders.getInstanceFor(type); + assertThat("Decoder instance", decoder, notNullValue()); T decoded = decoder.decode(value); - assertThat("Decoded", decoded, is(expectedDecoded)); } private void assertBinaryDecoder(Class type, ByteBuffer value, T expectedDecoded) throws IllegalAccessException, InstantiationException, DecodeException { - Class decoderClass = decoders.getDecoderFor(type); - assertThat("Decoder Class", decoderClass, notNullValue()); - - Decoder.Binary decoder = (Decoder.Binary) decoderClass.newInstance(); - decoder.init(testConfig); + Decoder.Binary decoder = (Decoder.Binary) decoders.getInstanceFor(type); + assertThat("Decoder Class", decoder, notNullValue()); T decoded = decoder.decode(value); - assertThat("Decoded", decoded, equalTo(expectedDecoded)); } @@ -194,6 +193,16 @@ public class AvailableDecodersTest byte expected[] = Hex.asByteArray("112233445566778899"); assertBinaryDecoder(byte[].class, val, expected); } + + @Test + public void testCustomDecoder_Integer() throws IllegalAccessException, InstantiationException, DecodeException + { + decoders.register(IntegerDecoder.class); + + String val = "11223344"; + int expected = 11223344; + assertTextDecoder(Integer.class, val, expected); + } @Test public void testCustomDecoder_Time() throws IllegalAccessException, InstantiationException, DecodeException @@ -260,6 +269,9 @@ public class AvailableDecodersTest public void testCustomDecoder_ValidDual_Text() throws IllegalAccessException, InstantiationException, DecodeException { decoders.register(ValidDualDecoder.class); + + AvailableDecoders.RegisteredDecoder registered = decoders.getRegisteredDecoderFor(Integer.class); + assertThat("Registered Decoder for Integer", registered.decoder.getName(), is(ValidDualDecoder.class.getName())); String val = "[1,234,567]"; Integer expected = 1234567; @@ -271,6 +283,9 @@ public class AvailableDecodersTest public void testCustomDecoder_ValidDual_Binary() throws IllegalAccessException, InstantiationException, DecodeException { decoders.register(ValidDualDecoder.class); + + AvailableDecoders.RegisteredDecoder registered = decoders.getRegisteredDecoderFor(Long.class); + assertThat("Registered Decoder for Long", registered.decoder.getName(), is(ValidDualDecoder.class.getName())); ByteBuffer val = ByteBuffer.allocate(16); val.put((byte) '['); @@ -281,4 +296,25 @@ public class AvailableDecodersTest assertBinaryDecoder(Long.class, val, expected); } + + @Test + public void testCustomDecoder_Register_Duplicate() + { + // has duplicated support for the same target Type + expectedException.expect(InvalidWebSocketException.class); + expectedException.expectMessage(containsString("Duplicate")); + decoders.register(BadDualDecoder.class); + } + + @Test + public void testCustomDecoder_Register_OtherDuplicate() + { + // Register DateDecoder (decodes java.util.Date) + decoders.register(DateDecoder.class); + + // Register TimeDecoder (which also wants to decode java.util.Date) + expectedException.expect(InvalidWebSocketException.class); + expectedException.expectMessage(containsString("Duplicate")); + decoders.register(TimeDecoder.class); + } } \ No newline at end of file diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/PrimitiveDecoderMetadataSetTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/PrimitiveDecoderMetadataSetTest.java deleted file mode 100644 index 95d05e6bc3f..00000000000 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/decoders/PrimitiveDecoderMetadataSetTest.java +++ /dev/null @@ -1,54 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.jsr356.decoders; - -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; - -import javax.websocket.Decoder; - -import org.eclipse.jetty.websocket.jsr356.MessageType; -import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadata; -import org.junit.Assert; -import org.junit.Test; - -public class PrimitiveDecoderMetadataSetTest -{ - private void assertClassEquals(String msg, Class actual, Class expected) - { - Assert.assertThat(msg,actual.getName(),is(expected.getName())); - } - - private void assertDecoderType(Class expectedDecoder, MessageType expectedMsgType, Class type) - { - PrimitiveDecoderMetadataSet primitives = new PrimitiveDecoderMetadataSet(); - DecoderMetadata metadata = primitives.getMetadataByType(type); - String prefix = String.format("Metadata By Type [%s]",type.getName()); - Assert.assertThat(prefix,metadata,notNullValue()); - - assertClassEquals(prefix + ".coderClass",metadata.getCoderClass(),expectedDecoder); - Assert.assertThat(prefix + ".messageType",metadata.getMessageType(),is(expectedMsgType)); - } - - @Test - public void testGetByteArray() - { - assertDecoderType(ByteArrayDecoder.class,MessageType.BINARY,byte[].class); - } -} diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/encoders/AvailableEncodersTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/encoders/AvailableEncodersTest.java index 8849132a822..be2656b9bc7 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/encoders/AvailableEncodersTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/encoders/AvailableEncodersTest.java @@ -18,6 +18,7 @@ package org.eclipse.jetty.websocket.jsr356.encoders; +import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThat; @@ -37,7 +38,9 @@ import javax.websocket.EndpointConfig; import org.eclipse.jetty.websocket.common.util.Hex; import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; public class AvailableEncodersTest { @@ -48,28 +51,24 @@ public class AvailableEncodersTest { testConfig = new EmptyClientEndpointConfig(); } - - private AvailableEncoders encoders = new AvailableEncoders(); + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + private AvailableEncoders encoders = new AvailableEncoders(testConfig); public void assertTextEncoder(Class type, T value, String expectedEncoded) throws IllegalAccessException, InstantiationException, EncodeException { - Class encoderClass = encoders.getEncoderFor(type); - assertThat("Encoder Class", encoderClass, notNullValue()); - - Encoder.Text encoder = (Encoder.Text) encoderClass.newInstance(); - encoder.init(testConfig); + Encoder.Text encoder = (Encoder.Text) encoders.getInstanceFor(type); + assertThat("Encoder", encoder, notNullValue()); String encoded = encoder.encode(value); - assertThat("Encoded", encoded, is(expectedEncoded)); } public void assertTextStreamEncoder(Class type, T value, String expectedEncoded) throws IllegalAccessException, InstantiationException, EncodeException, IOException { - Class encoderClass = encoders.getEncoderFor(type); - assertThat("Encoder Class", encoderClass, notNullValue()); - - Encoder.TextStream encoder = (Encoder.TextStream) encoderClass.newInstance(); - encoder.init(testConfig); + Encoder.TextStream encoder = (Encoder.TextStream) encoders.getInstanceFor(type); + assertThat("Encoder", encoder, notNullValue()); StringWriter writer = new StringWriter(); encoder.encode(value, writer); @@ -78,12 +77,8 @@ public class AvailableEncodersTest public void assertBinaryEncoder(Class type, T value, String expectedEncodedHex) throws IllegalAccessException, InstantiationException, EncodeException { - AvailableEncoders encoders = new AvailableEncoders(); - Class encoderClass = encoders.getEncoderFor(type); - assertThat("Encoder Class", encoderClass, notNullValue()); - - Encoder.Binary encoder = (Encoder.Binary) encoderClass.newInstance(); - encoder.init(testConfig); + Encoder.Binary encoder = (Encoder.Binary) encoders.getInstanceFor(type); + assertThat("Encoder", encoder, notNullValue()); ByteBuffer encoded = encoder.encode(value); String hexEncoded = Hex.asHex(encoded); @@ -92,11 +87,8 @@ public class AvailableEncodersTest public void assertBinaryStreamEncoder(Class type, T value, String expectedEncodedHex) throws IllegalAccessException, InstantiationException, EncodeException, IOException { - Class encoderClass = encoders.getEncoderFor(type); - assertThat("Encoder Class", encoderClass, notNullValue()); - - Encoder.BinaryStream encoder = (Encoder.BinaryStream) encoderClass.newInstance(); - encoder.init(testConfig); + Encoder.BinaryStream encoder = (Encoder.BinaryStream) encoders.getInstanceFor(type); + assertThat("Encoder", encoder, notNullValue()); ByteArrayOutputStream out = new ByteArrayOutputStream(); encoder.encode(value, out); @@ -210,6 +202,15 @@ public class AvailableEncodersTest byte buf[] = Hex.asByteArray("998877665544332211"); assertBinaryEncoder(byte[].class, buf, "998877665544332211"); } + + @Test + public void testCustomEncoder_Integer() throws IllegalAccessException, InstantiationException, EncodeException + { + encoders.register(IntegerEncoder.class); + int val = 99887766; + String expected = "99887766"; + assertTextEncoder(Integer.class, val, expected); + } @Test public void testCustomEncoder_Time() throws IllegalAccessException, InstantiationException, EncodeException, IOException @@ -274,4 +275,25 @@ public class AvailableEncodersTest long value = 0x112233445566L; assertBinaryStreamEncoder(Long.class, value, "5B00001122334455665D"); } + + @Test + public void testCustomEncoder_Register_Duplicate() + { + // has duplicated support for the same target Type + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage(containsString("Duplicate")); + encoders.register(BadDualEncoder.class); + } + + @Test + public void testCustomEncoder_Register_OtherDuplicate() + { + // Register DateEncoder (decodes java.util.Date) + encoders.register(DateEncoder.class); + + // Register TimeEncoder (which also wants to decode java.util.Date) + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage(containsString("Duplicate")); + encoders.register(TimeEncoder.class); + } } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_BadSignaturesTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_BadSignaturesTest.java index b212087bd27..2c475599b8c 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_BadSignaturesTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_BadSignaturesTest.java @@ -51,14 +51,22 @@ public class JsrEndpointFunctions_BadSignaturesTest { container = new ClientContainer(); } - - private AvailableEncoders encoders = new AvailableEncoders(); - private AvailableDecoders decoders = new AvailableDecoders(); - private Map uriParams = new HashMap<>(); - private EndpointConfig endpointConfig = new EmptyClientEndpointConfig(); - + @Rule public ExpectedException expectedException = ExpectedException.none(); + + private AvailableEncoders encoders; + private AvailableDecoders decoders; + private Map uriParams = new HashMap<>(); + private EndpointConfig endpointConfig; + + public JsrEndpointFunctions_BadSignaturesTest() + { + endpointConfig = new EmptyClientEndpointConfig(); + encoders = new AvailableEncoders(endpointConfig); + decoders = new AvailableDecoders(endpointConfig); + uriParams = new HashMap<>(); + } private void assertBadSocket(TrackingSocket socket, String expectedString) throws Exception { diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnCloseTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnCloseTest.java index 510def66d91..9aa4b8f57f5 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnCloseTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnCloseTest.java @@ -53,11 +53,19 @@ public class JsrEndpointFunctions_OnCloseTest { container = new ClientContainer(); } - - private AvailableEncoders encoders = new AvailableEncoders(); - private AvailableDecoders decoders = new AvailableDecoders(); - private Map uriParams = new HashMap<>(); - private EndpointConfig endpointConfig = new EmptyClientEndpointConfig(); + + private AvailableEncoders encoders; + private AvailableDecoders decoders; + private Map uriParams = new HashMap<>(); + private EndpointConfig endpointConfig; + + public JsrEndpointFunctions_OnCloseTest() + { + endpointConfig = new EmptyClientEndpointConfig(); + encoders = new AvailableEncoders(endpointConfig); + decoders = new AvailableDecoders(endpointConfig); + uriParams = new HashMap<>(); + } public JsrSession newSession(Object websocket) { diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnErrorTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnErrorTest.java index 0c2c9339832..8fa648d5101 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnErrorTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnErrorTest.java @@ -50,11 +50,19 @@ public class JsrEndpointFunctions_OnErrorTest { container = new ClientContainer(); } - - private AvailableEncoders encoders = new AvailableEncoders(); - private AvailableDecoders decoders = new AvailableDecoders(); + + private AvailableEncoders encoders; + private AvailableDecoders decoders; private Map uriParams = new HashMap<>(); - private EndpointConfig endpointConfig = new EmptyClientEndpointConfig(); + private EndpointConfig endpointConfig; + + public JsrEndpointFunctions_OnErrorTest() + { + endpointConfig = new EmptyClientEndpointConfig(); + encoders = new AvailableEncoders(endpointConfig); + decoders = new AvailableDecoders(endpointConfig); + uriParams = new HashMap<>(); + } public JsrSession newSession(Object websocket) { diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryTest.java index 28fe22a7755..9ae044686e4 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_BinaryTest.java @@ -21,24 +21,18 @@ package org.eclipse.jetty.websocket.jsr356.function; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; -import java.net.URI; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import javax.websocket.ClientEndpoint; -import javax.websocket.ClientEndpointConfig; import javax.websocket.EndpointConfig; import javax.websocket.OnMessage; import javax.websocket.Session; import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.test.DummyConnection; import org.eclipse.jetty.websocket.jsr356.ClientContainer; -import org.eclipse.jetty.websocket.jsr356.ConfiguredEndpoint; -import org.eclipse.jetty.websocket.jsr356.JsrSession; import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig; import org.eclipse.jetty.websocket.jsr356.decoders.AvailableDecoders; import org.eclipse.jetty.websocket.jsr356.encoders.AvailableEncoders; @@ -56,22 +50,18 @@ public class JsrEndpointFunctions_OnMessage_BinaryTest container = new ClientContainer(); } - private AvailableEncoders encoders = new AvailableEncoders(); - private AvailableDecoders decoders = new AvailableDecoders(); - private Map uriParams = new HashMap<>(); - private EndpointConfig endpointConfig = new EmptyClientEndpointConfig(); - private String expectedBuffer; + private AvailableEncoders encoders; + private AvailableDecoders decoders; + private Map uriParams = new HashMap<>(); + private EndpointConfig endpointConfig; - public JsrSession newSession(Object websocket) + public JsrEndpointFunctions_OnMessage_BinaryTest() { - String id = JsrEndpointFunctions_OnMessage_BinaryTest.class.getSimpleName(); - URI requestURI = URI.create("ws://localhost/" + id); - WebSocketPolicy policy = WebSocketPolicy.newClientPolicy(); - DummyConnection connection = new DummyConnection(policy); - ClientEndpointConfig config = new EmptyClientEndpointConfig(); - ConfiguredEndpoint ei = new ConfiguredEndpoint(websocket, config); - return new JsrSession(container, id, requestURI, ei, connection); + endpointConfig = new EmptyClientEndpointConfig(); + encoders = new AvailableEncoders(endpointConfig); + decoders = new AvailableDecoders(endpointConfig); + uriParams = new HashMap<>(); } private void assertOnMessageInvocation(TrackingSocket socket, String expectedEventFormat, Object... args) throws Exception diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextTest.java index a4b68f7fcff..3cf6c621207 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnMessage_TextTest.java @@ -21,24 +21,18 @@ package org.eclipse.jetty.websocket.jsr356.function; import static org.hamcrest.Matchers.containsString; import java.lang.reflect.InvocationTargetException; -import java.net.URI; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; -import javax.websocket.ClientEndpointConfig; import javax.websocket.EndpointConfig; import javax.websocket.OnMessage; import javax.websocket.Session; import org.eclipse.jetty.util.BufferUtil; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.common.InvalidSignatureException; -import org.eclipse.jetty.websocket.common.test.DummyConnection; import org.eclipse.jetty.websocket.jsr356.ClientContainer; -import org.eclipse.jetty.websocket.jsr356.ConfiguredEndpoint; -import org.eclipse.jetty.websocket.jsr356.JsrSession; import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig; import org.eclipse.jetty.websocket.jsr356.decoders.AvailableDecoders; import org.eclipse.jetty.websocket.jsr356.encoders.AvailableEncoders; @@ -57,24 +51,21 @@ public class JsrEndpointFunctions_OnMessage_TextTest { container = new ClientContainer(); } - - private AvailableEncoders encoders = new AvailableEncoders(); - private AvailableDecoders decoders = new AvailableDecoders(); - private Map uriParams = new HashMap<>(); - private EndpointConfig endpointConfig = new EmptyClientEndpointConfig(); - + @Rule public ExpectedException expectedException = ExpectedException.none(); - public JsrSession newSession(Object websocket) + private AvailableEncoders encoders; + private AvailableDecoders decoders; + private Map uriParams = new HashMap<>(); + private EndpointConfig endpointConfig; + + public JsrEndpointFunctions_OnMessage_TextTest() { - String id = JsrEndpointFunctions_OnMessage_TextTest.class.getSimpleName(); - URI requestURI = URI.create("ws://localhost/" + id); - WebSocketPolicy policy = WebSocketPolicy.newClientPolicy(); - DummyConnection connection = new DummyConnection(policy); - ClientEndpointConfig config = new EmptyClientEndpointConfig(); - ConfiguredEndpoint ei = new ConfiguredEndpoint(websocket, config); - return new JsrSession(container, id, requestURI, ei, connection); + endpointConfig = new EmptyClientEndpointConfig(); + encoders = new AvailableEncoders(endpointConfig); + decoders = new AvailableDecoders(endpointConfig); + uriParams = new HashMap<>(); } private void onText(TrackingSocket socket, String msg) diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnOpenTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnOpenTest.java index d26124d1de4..a0e7d92a9ab 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnOpenTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/function/JsrEndpointFunctions_OnOpenTest.java @@ -49,11 +49,19 @@ public class JsrEndpointFunctions_OnOpenTest { container = new ClientContainer(); } - - private AvailableEncoders encoders = new AvailableEncoders(); - private AvailableDecoders decoders = new AvailableDecoders(); - private Map uriParams = new HashMap<>(); - private EndpointConfig endpointConfig = new EmptyClientEndpointConfig(); + + private AvailableEncoders encoders; + private AvailableDecoders decoders; + private Map uriParams = new HashMap<>(); + private EndpointConfig endpointConfig; + + public JsrEndpointFunctions_OnOpenTest() + { + endpointConfig = new EmptyClientEndpointConfig(); + encoders = new AvailableEncoders(endpointConfig); + decoders = new AvailableDecoders(endpointConfig); + uriParams = new HashMap<>(); + } public JsrSession newSession(Object websocket) { diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/metadata/DecoderMetadataSetTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/metadata/DecoderMetadataSetTest.java deleted file mode 100644 index 3d1d0f8bd33..00000000000 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/metadata/DecoderMetadataSetTest.java +++ /dev/null @@ -1,134 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.jsr356.metadata; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; - -import java.util.List; - -import javax.websocket.Decoder; - -import org.eclipse.jetty.websocket.jsr356.MessageType; -import org.eclipse.jetty.websocket.jsr356.decoders.BadDualDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.DateDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.IntegerDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.TimeDecoder; -import org.eclipse.jetty.websocket.jsr356.decoders.ValidDualDecoder; -import org.junit.Assert; -import org.junit.Test; - -public class DecoderMetadataSetTest -{ - private void assertMetadata(CoderMetadata metadata, Class expectedType, Class expectedCoder, MessageType expectedMessageType) - { - Assert.assertEquals("metadata.coderClass",expectedCoder,metadata.getCoderClass()); - Assert.assertThat("metadata.messageType",metadata.getMessageType(),is(expectedMessageType)); - Assert.assertEquals("metadata.objectType",expectedType,metadata.getObjectType()); - } - - @Test - public void testAddBadDualDecoders() - { - try - { - DecoderMetadataSet coders = new DecoderMetadataSet(); - - // has duplicated support for the same target Type - coders.add(BadDualDecoder.class); - Assert.fail("Should have thrown IllegalStateException for attempting to register Decoders with duplicate implementation"); - } - catch (IllegalStateException e) - { - Assert.assertThat(e.getMessage(),containsString("Duplicate")); - } - } - - @Test - public void testAddDuplicate() - { - DecoderMetadataSet coders = new DecoderMetadataSet(); - - // Add DateDecoder (decodes java.util.Date) - coders.add(DateDecoder.class); - - try - { - // Add TimeDecoder (which also wants to decode java.util.Date) - coders.add(TimeDecoder.class); - Assert.fail("Should have thrown IllegalStateException for attempting to register Decoders with duplicate implementation"); - } - catch (IllegalStateException e) - { - Assert.assertThat(e.getMessage(),containsString("Duplicate")); - } - } - - @Test - public void testAddGetCoder() - { - DecoderMetadataSet coders = new DecoderMetadataSet(); - - coders.add(IntegerDecoder.class); - Class actualClazz = coders.getCoder(Integer.class); - Assert.assertEquals("Coder Class",IntegerDecoder.class,actualClazz); - } - - @Test - public void testAddGetMetadataByImpl() - { - DecoderMetadataSet coders = new DecoderMetadataSet(); - - coders.add(IntegerDecoder.class); - List metadatas = coders.getMetadataByImplementation(IntegerDecoder.class); - Assert.assertThat("Metadatas (by impl) count",metadatas.size(),is(1)); - DecoderMetadata metadata = metadatas.get(0); - assertMetadata(metadata,Integer.class,IntegerDecoder.class,MessageType.TEXT); - } - - @Test - public void testAddGetMetadataByType() - { - DecoderMetadataSet coders = new DecoderMetadataSet(); - - coders.add(IntegerDecoder.class); - DecoderMetadata metadata = coders.getMetadataByType(Integer.class); - assertMetadata(metadata,Integer.class,IntegerDecoder.class,MessageType.TEXT); - } - - @Test - public void testAddValidDualDecoders() - { - DecoderMetadataSet coders = new DecoderMetadataSet(); - - coders.add(ValidDualDecoder.class); - - List> decodersList = coders.getList(); - Assert.assertThat("Decoder List",decodersList,notNullValue()); - Assert.assertThat("Decoder List count",decodersList.size(),is(2)); - - DecoderMetadata metadata; - metadata = coders.getMetadataByType(Integer.class); - assertMetadata(metadata,Integer.class,ValidDualDecoder.class,MessageType.TEXT); - - metadata = coders.getMetadataByType(Long.class); - assertMetadata(metadata,Long.class,ValidDualDecoder.class,MessageType.BINARY); - } -} diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/metadata/EncoderMetadataSetTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/metadata/EncoderMetadataSetTest.java deleted file mode 100644 index e2684992383..00000000000 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/metadata/EncoderMetadataSetTest.java +++ /dev/null @@ -1,134 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.eclipse.jetty.websocket.jsr356.metadata; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; - -import java.util.List; - -import javax.websocket.Encoder; - -import org.eclipse.jetty.websocket.jsr356.MessageType; -import org.eclipse.jetty.websocket.jsr356.encoders.BadDualEncoder; -import org.eclipse.jetty.websocket.jsr356.encoders.DateEncoder; -import org.eclipse.jetty.websocket.jsr356.encoders.IntegerEncoder; -import org.eclipse.jetty.websocket.jsr356.encoders.TimeEncoder; -import org.eclipse.jetty.websocket.jsr356.encoders.ValidDualEncoder; -import org.junit.Assert; -import org.junit.Test; - -public class EncoderMetadataSetTest -{ - private void assertMetadata(CoderMetadata metadata, Class expectedType, Class expectedCoder, MessageType expectedMessageType) - { - Assert.assertEquals("metadata.coderClass",expectedCoder,metadata.getCoderClass()); - Assert.assertThat("metadata.messageType",metadata.getMessageType(),is(expectedMessageType)); - Assert.assertEquals("metadata.objectType",expectedType,metadata.getObjectType()); - } - - @Test - public void testAddBadDualEncoders() - { - try - { - EncoderMetadataSet coders = new EncoderMetadataSet(); - - // has duplicated support for the same target Type - coders.add(BadDualEncoder.class); - Assert.fail("Should have thrown IllegalStateException for attempting to register AvailableEncoders with duplicate implementation"); - } - catch (IllegalStateException e) - { - Assert.assertThat(e.getMessage(),containsString("Duplicate")); - } - } - - @Test - public void testAddDuplicate() - { - EncoderMetadataSet coders = new EncoderMetadataSet(); - - // Add DateEncoder (decodes java.util.Date) - coders.add(DateEncoder.class); - - try - { - // Add TimeEncoder (which also wants to decode java.util.Date) - coders.add(TimeEncoder.class); - Assert.fail("Should have thrown IllegalStateException for attempting to register AvailableEncoders with duplicate implementation"); - } - catch (IllegalStateException e) - { - Assert.assertThat(e.getMessage(),containsString("Duplicate")); - } - } - - @Test - public void testAddGetCoder() - { - EncoderMetadataSet coders = new EncoderMetadataSet(); - - coders.add(IntegerEncoder.class); - Class actualClazz = coders.getCoder(Integer.class); - Assert.assertEquals("Coder Class",IntegerEncoder.class,actualClazz); - } - - @Test - public void testAddGetMetadataByImpl() - { - EncoderMetadataSet coders = new EncoderMetadataSet(); - - coders.add(IntegerEncoder.class); - List metadatas = coders.getMetadataByImplementation(IntegerEncoder.class); - Assert.assertThat("Metadatas (by impl) count",metadatas.size(),is(1)); - EncoderMetadata metadata = metadatas.get(0); - assertMetadata(metadata,Integer.class,IntegerEncoder.class,MessageType.TEXT); - } - - @Test - public void testAddGetMetadataByType() - { - EncoderMetadataSet coders = new EncoderMetadataSet(); - - coders.add(IntegerEncoder.class); - EncoderMetadata metadata = coders.getMetadataByType(Integer.class); - assertMetadata(metadata,Integer.class,IntegerEncoder.class,MessageType.TEXT); - } - - @Test - public void testAddValidDualEncoders() - { - EncoderMetadataSet coders = new EncoderMetadataSet(); - - coders.add(ValidDualEncoder.class); - - List> EncodersList = coders.getList(); - Assert.assertThat("Encoder List",EncodersList,notNullValue()); - Assert.assertThat("Encoder List count",EncodersList.size(),is(2)); - - EncoderMetadata metadata; - metadata = coders.getMetadataByType(Integer.class); - assertMetadata(metadata,Integer.class,ValidDualEncoder.class,MessageType.TEXT); - - metadata = coders.getMetadataByType(Long.class); - assertMetadata(metadata,Long.class,ValidDualEncoder.class,MessageType.BINARY); - } -} diff --git a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctions.java b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctions.java index 5e597d1f02d..7af2603a2c3 100644 --- a/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctions.java +++ b/jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/function/CommonEndpointFunctions.java @@ -479,16 +479,51 @@ public class CommonEndpointFunctions extends AbstractLifeCycl throw new InvalidSignatureException(err.toString()); } + protected void clearOnPongFunction() + { + + } + + protected void clearOnTextSink() + { + + } + + protected void clearOnBinarySink() + { + + } + public BatchMode getBatchMode() { return batchMode; } + public Executor getExecutor() + { + return executor; + } + public T getSession() { return session; } + protected MessageSink getOnTextSink() + { + return onTextSink; + } + + protected MessageSink getOnBinarySink() + { + return onBinarySink; + } + + protected Function getOnPongFunction() + { + return onPongFunction; + } + public void setOnOpen(Function function, Object origin) { assertNotSet(this.onOpenFunction, "Open Handler", origin);