diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/AnnotatedEndpointScanner.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/AnnotatedEndpointScanner.java new file mode 100644 index 00000000000..8369b42fbf7 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/AnnotatedEndpointScanner.java @@ -0,0 +1,169 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.util.LinkedList; +import java.util.List; + +import javax.websocket.OnClose; +import javax.websocket.OnError; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; + +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.common.events.annotated.AbstractMethodAnnotationScanner; +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; + +public class AnnotatedEndpointScanner extends AbstractMethodAnnotationScanner> +{ + private static final Logger LOG = Log.getLogger(AnnotatedEndpointScanner.class); + + private final LinkedList paramsOnOpen; + private final LinkedList paramsOnClose; + private final LinkedList paramsOnError; + private final LinkedList paramsOnMessage; + private final JsrMetadata metadata; + + public AnnotatedEndpointScanner(JsrMetadata metadata) + { + this.metadata = metadata; + + paramsOnOpen = new LinkedList<>(); + paramsOnClose = new LinkedList<>(); + paramsOnError = new LinkedList<>(); + paramsOnMessage = new LinkedList<>(); + + paramsOnOpen.add(JsrParamIdOnOpen.INSTANCE); + metadata.customizeParamsOnOpen(paramsOnOpen); + paramsOnClose.add(JsrParamIdOnClose.INSTANCE); + metadata.customizeParamsOnClose(paramsOnClose); + paramsOnError.add(JsrParamIdOnError.INSTANCE); + metadata.customizeParamsOnError(paramsOnError); + + paramsOnMessage.add(JsrParamIdBinary.INSTANCE); + paramsOnMessage.add(JsrParamIdText.INSTANCE); + paramsOnMessage.add(JsrParamIdPong.INSTANCE); + metadata.customizeParamsOnMessage(paramsOnMessage); + } + + private ParameterizedMethod establishCallable(JsrMetadata metadata, Class pojo, Method method, List paramIds, + Class methodAnnotationClass) + { + ParameterizedMethod jpm = new ParameterizedMethod(pojo,method); + + // Identify all of the parameters + for (Param param : jpm) + { + if (!identifyParam(param,jpm,metadata,paramIds)) + { + StringBuilder err = new StringBuilder(); + err.append("Encountered invalid parameter <"); + err.append(param.type.getName()); + err.append("> on @"); + err.append(methodAnnotationClass.getSimpleName()); + err.append(" annotated method: "); + err.append(jpm.getFullyQualifiedMethodName()); + + throw new InvalidSignatureException(err.toString()); + } + } + + return jpm; + } + + private boolean identifyParam(Param param, ParameterizedMethod jpm, JsrMetadata metadata2, List paramIds) + { + for (IJsrParamId paramId : paramIds) + { + if (paramId.process(param.type,jpm,metadata)) + { + // identified the parameter + param.setValid(true); + return true; + } + } + + // Didn't pass any of the param ids + return false; + } + + @Override + public void onMethodAnnotation(JsrMetadata metadata, Class pojo, Method method, Annotation annotation) + { + LOG.debug("onMethodAnnotation({}, {}, {}, {})",metadata,pojo,method,annotation); + + if (isAnnotation(annotation,OnOpen.class)) + { + assertIsPublicNonStatic(method); + assertIsReturn(method,Void.TYPE); + metadata.onOpen = establishCallable(metadata,pojo,method,paramsOnOpen,OnOpen.class); + return; + } + + if (isAnnotation(annotation,OnClose.class)) + { + assertIsPublicNonStatic(method); + assertIsReturn(method,Void.TYPE); + metadata.onClose = establishCallable(metadata,pojo,method,paramsOnClose,OnClose.class); + return; + } + + if (isAnnotation(annotation,OnError.class)) + { + assertIsPublicNonStatic(method); + assertIsReturn(method,Void.TYPE); + metadata.onError = establishCallable(metadata,pojo,method,paramsOnError,OnError.class); + return; + } + + if (isAnnotation(annotation,OnMessage.class)) + { + assertIsPublicNonStatic(method); + assertIsReturn(method,Void.TYPE); + ParameterizedMethod msgMethod = establishCallable(metadata,pojo,method,paramsOnMessage,OnMessage.class); + switch (msgMethod.getMessageType()) + { + case TEXT: + metadata.onText = msgMethod; + break; + case BINARY: + metadata.onBinary = msgMethod; + break; + case PONG: + metadata.onPong = msgMethod; + break; + default: + StringBuilder err = new StringBuilder(); + err.append("Invalid @OnMessage method signature,"); + err.append(" Missing type TEXT, BINARY, or PONG parameter: "); + err.append(msgMethod.getFullyQualifiedMethodName()); + throw new InvalidSignatureException(err.toString()); + } + } + } + + public JsrMetadata scan() + { + scanMethodAnnotations(metadata,metadata.pojo); + return metadata; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/IJsrMethod.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/IJsrMethod.java new file mode 100644 index 00000000000..ef4b1aec82f --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/IJsrMethod.java @@ -0,0 +1,93 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import java.lang.reflect.Method; + +import javax.websocket.Decoder; +import javax.websocket.OnMessage; + +public interface IJsrMethod +{ + /** + * There can only be 1 of each kind of MessageType in a class + */ + public static enum MessageType + { + UNKNOWN, + TEXT, + BINARY, + PONG + } + + /** + * Indicate that partial message support is desired + */ + void enablePartialMessageSupport(); + + /** + * Get the fully qualifed method name {classname}.{methodname}({params}) suitable for using in error messages. + * + * @return the fully qualified method name for end users + */ + String getFullyQualifiedMethodName(); + + /** + * Get the Decoder to use for message decoding + * + * @return the decoder class to use for message decoding + */ + Class getMessageDecoder(); + + /** + * The type of message this method can handle + * + * @return the message type if @{@link OnMessage} annotated, {@link MessageType#UNKNOWN} if unknown/unspecified + */ + MessageType getMessageType(); + + /** + * The reflected method + * + * @return the method itself + */ + Method getMethod(); + + /** + * Indicator that partial message support is enabled + * + * @return true if enabled + */ + boolean isPartialMessageSupportEnabled(); + + /** + * The message decoder class to use. + * + * @param decoderClass + */ + void setMessageDecoder(Class decoderClass); + + /** + * The type of message this method can handle + * + * @param type + * the type of message + */ + void setMessageType(MessageType type); +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/IJsrParamId.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/IJsrParamId.java new file mode 100644 index 00000000000..bacd3a492dc --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/IJsrParamId.java @@ -0,0 +1,46 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; + +/** + * JSR-356 Parameter Identification processing. + */ +public interface IJsrParamId +{ + /** + * Process the potential parameter. + *

+ * Primary purpose is to indicate if this is a valid parameter or not by returning true for a known valid parameter type, false for a parameter type that + * was not handled by this IJsrParamId. And throwing a InvalidSignatureException if the parameter violates a rule that the IJsrParamId is aware of. + * + * @param type + * the parameter type being processed + * @param method + * the method this type belongs to + * @param metadata + * the metadata for this pojo + * + * @return true if processed, false if not processed + * @throws InvalidSignatureException + * if a violation of the signature rules occurred + */ + boolean process(Class type, IJsrMethod method, JsrMetadata metadata) throws InvalidSignatureException; +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrMetadata.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrMetadata.java new file mode 100644 index 00000000000..04d4c729fe1 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrMetadata.java @@ -0,0 +1,94 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import java.lang.annotation.Annotation; +import java.util.LinkedList; + +import javax.websocket.OnClose; +import javax.websocket.OnError; +import javax.websocket.OnMessage; +import javax.websocket.OnOpen; + +import org.eclipse.jetty.websocket.jsr356.decoders.Decoders; +import org.eclipse.jetty.websocket.jsr356.encoders.Encoders; + +public abstract class JsrMetadata +{ + public final Class pojo; + public Decoders decoders; + public Encoders encoders; + + /** + * Callable for @{@link OnOpen} annotation + */ + public ParameterizedMethod onOpen; + + /** + * Callable for @{@link OnClose} annotation + */ + public ParameterizedMethod onClose; + + /** + * Callable for @{@link OnError} annotation + */ + public ParameterizedMethod onError; + + /** + * Callable for @{@link OnMessage} annotation dealing with Text Message Format + */ + public ParameterizedMethod onText; + + /** + * Callable for @{@link OnMessage} annotation dealing with Binary Message Format + */ + public ParameterizedMethod onBinary; + + /** + * Callable for @{@link OnMessage} annotation dealing with Pong Message Format + */ + public ParameterizedMethod onPong; + + protected JsrMetadata(Class websocket) + { + this.pojo = websocket; + } + + public void customizeParamsOnClose(LinkedList params) + { + /* do nothing */ + } + + public void customizeParamsOnError(LinkedList params) + { + /* do nothing */ + } + + public void customizeParamsOnMessage(LinkedList params) + { + /* do nothing */ + } + + public void customizeParamsOnOpen(LinkedList params) + { + /* do nothing */ + } + + public abstract T getAnnotation(); +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdBinary.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdBinary.java new file mode 100644 index 00000000000..9a0b922a884 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdBinary.java @@ -0,0 +1,84 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import java.nio.ByteBuffer; + +import javax.websocket.Decoder; +import javax.websocket.OnMessage; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; +import org.eclipse.jetty.websocket.jsr356.annotations.IJsrMethod.MessageType; +import org.eclipse.jetty.websocket.jsr356.decoders.ByteArrayDecoder; +import org.eclipse.jetty.websocket.jsr356.decoders.ByteBufferDecoder; + +/** + * Param handling for static Binary @{@link OnMessage} parameters. + */ +public class JsrParamIdBinary extends JsrParamIdOnMessage implements IJsrParamId +{ + public static final IJsrParamId INSTANCE = new JsrParamIdBinary(); + + @Override + public boolean process(Class type, IJsrMethod method, JsrMetadata metadata) throws InvalidSignatureException + { + if (type.isAssignableFrom(ByteBuffer.class)) + { + method.setMessageType(MessageType.BINARY); + method.setMessageDecoder(ByteBufferDecoder.class); + return true; + } + + if (type.isAssignableFrom(byte[].class)) + { + method.setMessageType(MessageType.BINARY); + method.setMessageDecoder(ByteArrayDecoder.class); + return true; + } + + // Boolean (for indicating partial message support) + if (type.isAssignableFrom(Boolean.TYPE)) + { + Class decoder = method.getMessageDecoder(); + if (decoder == null) + { + // specific decoder technique not identified yet + method.enablePartialMessageSupport(); + } + else + { + if (decoder.isAssignableFrom(ByteBufferDecoder.class) || decoder.isAssignableFrom(ByteArrayDecoder.class)) + { + method.enablePartialMessageSupport(); + } + else + { + StringBuilder err = new StringBuilder(); + err.append("Unable to support boolean <"); + err.append(type.getName()).append("> as partial message indicator "); + err.append("for a binary message parameter that is not a "); + err.append(ByteBuffer.class.getName()).append(" or byte[]"); + throw new InvalidSignatureException(err.toString()); + } + } + return true; + } + return false; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdBinaryDecoder.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdBinaryDecoder.java new file mode 100644 index 00000000000..66c96486eb3 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdBinaryDecoder.java @@ -0,0 +1,52 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import javax.websocket.Decoder; +import javax.websocket.OnMessage; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; +import org.eclipse.jetty.websocket.jsr356.annotations.IJsrMethod.MessageType; +import org.eclipse.jetty.websocket.jsr356.decoders.Decoders.DecoderRef; + +/** + * Param handling for Binary @{@link OnMessage} parameters declared as {@link Decoder}s of type {@link Decoder.Binary} or {@link Decoder.BinaryStream} + */ +public class JsrParamIdBinaryDecoder extends JsrParamIdOnMessage implements IJsrParamId +{ + private final DecoderRef ref; + + public JsrParamIdBinaryDecoder(DecoderRef ref) + { + this.ref = ref; + } + + @Override + public boolean process(Class type, IJsrMethod method, JsrMetadata metadata) throws InvalidSignatureException + { + if (type.isAssignableFrom(ref.getType())) + { + assertPartialMessageSupportDisabled(type,method); + method.setMessageType(MessageType.BINARY); + method.setMessageDecoder(ref.getDecoder()); + return true; + } + return false; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnClose.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnClose.java new file mode 100644 index 00000000000..f4f81f684b0 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnClose.java @@ -0,0 +1,43 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import javax.websocket.CloseReason; +import javax.websocket.OnClose; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; + +/** + * Param handling for @{@link OnClose} parameters. + */ +public class JsrParamIdOnClose implements IJsrParamId +{ + public static final IJsrParamId INSTANCE = new JsrParamIdOnClose(); + + @Override + public boolean process(Class type, IJsrMethod method, JsrMetadata metadata) throws InvalidSignatureException + { + if (type.isAssignableFrom(CloseReason.class) || type.isAssignableFrom(Session.class)) + { + return true; + } + return false; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnError.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnError.java new file mode 100644 index 00000000000..2d0ab70d3e2 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnError.java @@ -0,0 +1,42 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import javax.websocket.OnError; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; + +/** + * Param handling for @{@link OnError} parameters. + */ +public class JsrParamIdOnError implements IJsrParamId +{ + public static final IJsrParamId INSTANCE = new JsrParamIdOnError(); + + @Override + public boolean process(Class type, IJsrMethod method, JsrMetadata metadata) throws InvalidSignatureException + { + if (type.isAssignableFrom(Throwable.class) || type.isAssignableFrom(Session.class)) + { + return true; + } + return false; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnMessage.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnMessage.java new file mode 100644 index 00000000000..1b28894d01e --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnMessage.java @@ -0,0 +1,36 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; + +public abstract class JsrParamIdOnMessage implements IJsrParamId +{ + protected void assertPartialMessageSupportDisabled(Class type, IJsrMethod method) + { + if (method.isPartialMessageSupportEnabled()) + { + StringBuilder err = new StringBuilder(); + err.append("Unable to support parameter type <"); + err.append(type.getName()).append("> in conjunction with the partial message indicator boolean."); + err.append(" Only type is supported with partial message boolean indicator."); + throw new InvalidSignatureException(err.toString()); + } + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnOpen.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnOpen.java new file mode 100644 index 00000000000..f9fc9381ef2 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdOnOpen.java @@ -0,0 +1,43 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import javax.websocket.EndpointConfig; +import javax.websocket.OnOpen; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; + +/** + * Param handling for @{@link OnOpen} parameters. + */ +public class JsrParamIdOnOpen implements IJsrParamId +{ + public static final IJsrParamId INSTANCE = new JsrParamIdOnOpen(); + + @Override + public boolean process(java.lang.Class type, IJsrMethod method, JsrMetadata metadata) throws InvalidSignatureException + { + if (type.isAssignableFrom(EndpointConfig.class) || type.isAssignableFrom(Session.class)) + { + return true; + } + return false; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdPong.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdPong.java new file mode 100644 index 00000000000..2050e51f9ff --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdPong.java @@ -0,0 +1,43 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import javax.websocket.PongMessage; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; +import org.eclipse.jetty.websocket.jsr356.annotations.IJsrMethod.MessageType; +import org.eclipse.jetty.websocket.jsr356.decoders.PongMessageDecoder; + +public class JsrParamIdPong extends JsrParamIdOnMessage implements IJsrParamId +{ + public static final IJsrParamId INSTANCE = new JsrParamIdPong(); + + @Override + public boolean process(Class type, IJsrMethod method, JsrMetadata metadata) throws InvalidSignatureException + { + if (type.isAssignableFrom(PongMessage.class)) + { + assertPartialMessageSupportDisabled(type,method); + method.setMessageType(MessageType.PONG); + method.setMessageDecoder(PongMessageDecoder.class); + return true; + } + return false; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdText.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdText.java new file mode 100644 index 00000000000..2ef77f9a160 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdText.java @@ -0,0 +1,141 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import javax.websocket.Decoder; +import javax.websocket.OnMessage; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; +import org.eclipse.jetty.websocket.jsr356.annotations.IJsrMethod.MessageType; +import org.eclipse.jetty.websocket.jsr356.decoders.BooleanDecoder; +import org.eclipse.jetty.websocket.jsr356.decoders.ByteDecoder; +import org.eclipse.jetty.websocket.jsr356.decoders.CharacterDecoder; +import org.eclipse.jetty.websocket.jsr356.decoders.DoubleDecoder; +import org.eclipse.jetty.websocket.jsr356.decoders.FloatDecoder; +import org.eclipse.jetty.websocket.jsr356.decoders.IntegerDecoder; +import org.eclipse.jetty.websocket.jsr356.decoders.LongDecoder; +import org.eclipse.jetty.websocket.jsr356.decoders.ShortDecoder; +import org.eclipse.jetty.websocket.jsr356.decoders.StringDecoder; + +/** + * Param handling for static Text @{@link OnMessage} parameters + */ +public class JsrParamIdText extends JsrParamIdOnMessage implements IJsrParamId +{ + public static final IJsrParamId INSTANCE = new JsrParamIdText(); + + @Override + public boolean process(Class type, IJsrMethod method, JsrMetadata metadata) throws InvalidSignatureException + { + // String for whole message + if (type.isAssignableFrom(String.class)) + { + method.setMessageType(MessageType.TEXT); + method.setMessageDecoder(StringDecoder.class); + return true; + } + + // Java primitive or class equivalent to receive the whole message converted to that type + if (type.isAssignableFrom(Boolean.class)) + { + assertPartialMessageSupportDisabled(type,method); + method.setMessageType(MessageType.TEXT); + method.setMessageDecoder(BooleanDecoder.class); + return true; + } + if (type.isAssignableFrom(Byte.class)) + { + assertPartialMessageSupportDisabled(type,method); + method.setMessageType(MessageType.TEXT); + method.setMessageDecoder(ByteDecoder.class); + return true; + } + if (type.isAssignableFrom(Character.class)) + { + assertPartialMessageSupportDisabled(type,method); + method.setMessageType(MessageType.TEXT); + method.setMessageDecoder(CharacterDecoder.class); + return true; + } + if (type.isAssignableFrom(Double.class)) + { + assertPartialMessageSupportDisabled(type,method); + method.setMessageType(MessageType.TEXT); + method.setMessageDecoder(DoubleDecoder.class); + return true; + } + if (type.isAssignableFrom(Float.class)) + { + assertPartialMessageSupportDisabled(type,method); + method.setMessageType(MessageType.TEXT); + method.setMessageDecoder(FloatDecoder.class); + return true; + } + if (type.isAssignableFrom(Integer.class)) + { + assertPartialMessageSupportDisabled(type,method); + method.setMessageType(MessageType.TEXT); + method.setMessageDecoder(IntegerDecoder.class); + return true; + } + if (type.isAssignableFrom(Long.class)) + { + assertPartialMessageSupportDisabled(type,method); + method.setMessageType(MessageType.TEXT); + method.setMessageDecoder(LongDecoder.class); + return true; + } + if (type.isAssignableFrom(Short.class)) + { + assertPartialMessageSupportDisabled(type,method); + method.setMessageType(MessageType.TEXT); + method.setMessageDecoder(ShortDecoder.class); + return true; + } + + // Boolean (for indicating partial message support) + if (type.isAssignableFrom(Boolean.TYPE)) + { + Class decoder = method.getMessageDecoder(); + if (decoder == null) + { + // specific decoder technique not identified yet + method.enablePartialMessageSupport(); + } + else + { + if (decoder.isAssignableFrom(StringDecoder.class)) + { + method.enablePartialMessageSupport(); + } + else + { + StringBuilder err = new StringBuilder(); + err.append("Unable to support boolean <"); + err.append(type.getName()).append("> as partial message indicator "); + err.append("in conjunction with a non-String text message parameter."); + throw new InvalidSignatureException(err.toString()); + } + } + return true; + } + + return false; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdTextDecoder.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdTextDecoder.java new file mode 100644 index 00000000000..0facaaecf58 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrParamIdTextDecoder.java @@ -0,0 +1,52 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import javax.websocket.Decoder; +import javax.websocket.OnMessage; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; +import org.eclipse.jetty.websocket.jsr356.annotations.IJsrMethod.MessageType; +import org.eclipse.jetty.websocket.jsr356.decoders.Decoders.DecoderRef; + +/** + * Param handling for Text @{@link OnMessage} parameters declared as {@link Decoder}s of type {@link Decoder.Text} or {@link Decoder.TextStream} + */ +public class JsrParamIdTextDecoder extends JsrParamIdOnMessage implements IJsrParamId +{ + private final DecoderRef ref; + + public JsrParamIdTextDecoder(DecoderRef ref) + { + this.ref = ref; + } + + @Override + public boolean process(Class type, IJsrMethod method, JsrMetadata metadata) throws InvalidSignatureException + { + if (type.isAssignableFrom(ref.getType())) + { + assertPartialMessageSupportDisabled(type,method); + method.setMessageType(MessageType.TEXT); + method.setMessageDecoder(ref.getDecoder()); + return true; + } + return false; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/Param.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/Param.java new file mode 100644 index 00000000000..e60262b0fd6 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/Param.java @@ -0,0 +1,35 @@ +package org.eclipse.jetty.websocket.jsr356.annotations; + +public class Param +{ + public int index; + public Class type; + private boolean valid = false; + private String pathParamVariable = null; + + public Param(int idx, Class type) + { + this.index = idx; + this.type = type; + } + + public String getPathParamVariable() + { + return this.pathParamVariable; + } + + public boolean isValid() + { + return valid; + } + + public void setPathParamVariable(String name) + { + this.pathParamVariable = name; + } + + public void setValid(boolean flag) + { + this.valid = flag; + } +} \ No newline at end of file diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/ParameterizedMethod.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/ParameterizedMethod.java new file mode 100644 index 00000000000..a7e264fb419 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/ParameterizedMethod.java @@ -0,0 +1,178 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.websocket.Decoder; + +import org.eclipse.jetty.websocket.common.events.annotated.CallableMethod; + +public class ParameterizedMethod extends CallableMethod implements IJsrMethod, Iterable +{ + static StringBuilder appendTypeName(StringBuilder sb, Type type, boolean ellipses) + { + if (type instanceof Class) + { + Class ctype = (Class)type; + if (ctype.isArray()) + { + try + { + int dimensions = 0; + while (ctype.isArray()) + { + dimensions++; + ctype = ctype.getComponentType(); + } + sb.append(ctype.getName()); + for (int i = 0; i < dimensions; i++) + { + if (ellipses) + { + sb.append("..."); + } + else + { + sb.append("[]"); + } + } + return sb; + } + catch (Throwable ignore) + { + // ignore + } + } + + sb.append(ctype.getName()); + } + else + { + sb.append(type.toString()); + } + + return sb; + } + + private List methodParams = new ArrayList<>(); + private MessageType messageType = MessageType.UNKNOWN; + + public ParameterizedMethod(Class pojo, Method method) + { + super(pojo,method); + + Class ptypes[] = method.getParameterTypes(); + int len = ptypes.length; + for (int i = 0; i < len; i++) + { + methodParams.add(new Param(i,ptypes[i])); + } + } + + @Override + public void enablePartialMessageSupport() + { + // TODO Auto-generated method stub + + } + + @Override + public String getFullyQualifiedMethodName() + { + StringBuilder str = new StringBuilder(); + str.append(getPojo().getName()); + str.append(" "); + Method method = getMethod(); + // method modifiers + int mod = method.getModifiers() & Modifier.methodModifiers(); + if (mod != 0) + { + str.append(Modifier.toString(mod)).append(' '); + } + + // return type + Type retType = method.getGenericReturnType(); + appendTypeName(str,retType,false).append(' '); + + // method name + str.append(method.getName()); + + // method parameters + str.append('('); + Type[] params = method.getGenericParameterTypes(); + for (int j = 0; j < params.length; j++) + { + boolean ellipses = method.isVarArgs() && (j == (params.length - 1)); + appendTypeName(str,params[j],ellipses); + if (j < (params.length - 1)) + { + str.append(", "); + } + } + str.append(')'); + + // TODO: show exceptions? + return str.toString(); + } + + @Override + public Class getMessageDecoder() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public MessageType getMessageType() + { + return this.messageType; + } + + @Override + public boolean isPartialMessageSupportEnabled() + { + // TODO Auto-generated method stub + return false; + } + + @Override + public Iterator iterator() + { + return methodParams.iterator(); + } + + @Override + public void setMessageDecoder(Class decoderClass) + { + // TODO Auto-generated method stub + + } + + @Override + public void setMessageType(MessageType type) + { + this.messageType = type; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/ByteArrayDecoder.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/ByteArrayDecoder.java new file mode 100644 index 00000000000..402831038d9 --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/ByteArrayDecoder.java @@ -0,0 +1,42 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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 java.nio.ByteBuffer; + +import javax.websocket.DecodeException; +import javax.websocket.Decoder; + +import org.eclipse.jetty.util.BufferUtil; + +public class ByteArrayDecoder extends AbstractDecoder implements Decoder.Binary +{ + @Override + public byte[] decode(ByteBuffer bytes) throws DecodeException + { + return BufferUtil.toArray(bytes); + } + + @Override + public boolean willDecode(ByteBuffer bytes) + { + return true; + } + +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/Decoders.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/Decoders.java index 2b037764690..79967e6867f 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/Decoders.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/Decoders.java @@ -22,17 +22,19 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import javax.websocket.Decoder; import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; import org.eclipse.jetty.websocket.jsr356.ConfigurationException; +import org.eclipse.jetty.websocket.jsr356.decoders.Decoders.DecoderRef; import org.eclipse.jetty.websocket.jsr356.utils.DeploymentTypeUtils; -public class Decoders +public class Decoders implements Iterable { - private static class DecoderRef + public static class DecoderRef { Class type; Class decoder; @@ -42,6 +44,16 @@ public class Decoders this.type = type; this.decoder = decoder; } + + public Class getDecoder() + { + return decoder; + } + + public Class getType() + { + return type; + } } public static List getDecoderInterfaces(Class decoder) @@ -188,4 +200,10 @@ public class Decoders throw new ConfigurationException("Unable to instantiate Decoder: " + decoderClass,e); } } + + @Override + public Iterator iterator() + { + return decoders.iterator(); + } } diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/PongMessageDecoder.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/PongMessageDecoder.java new file mode 100644 index 00000000000..5ab088b4a2d --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/decoders/PongMessageDecoder.java @@ -0,0 +1,43 @@ +package org.eclipse.jetty.websocket.jsr356.decoders; + +import java.nio.ByteBuffer; + +import javax.websocket.DecodeException; +import javax.websocket.Decoder; +import javax.websocket.PongMessage; + +import org.eclipse.jetty.util.BufferUtil; + +public class PongMessageDecoder extends AbstractDecoder implements Decoder.Binary +{ + private static class PongMsg implements PongMessage + { + private final ByteBuffer bytes; + + public PongMsg(ByteBuffer buf) + { + int len = buf.remaining(); + this.bytes = ByteBuffer.allocate(len); + BufferUtil.put(buf,this.bytes); + BufferUtil.flipToFlush(this.bytes,0); + } + + @Override + public ByteBuffer getApplicationData() + { + return this.bytes; + } + } + + @Override + public PongMessage decode(ByteBuffer bytes) throws DecodeException + { + return new PongMsg(bytes); + } + + @Override + public boolean willDecode(ByteBuffer bytes) + { + return true; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientImpl.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientImpl.java deleted file mode 100644 index 3eccd2c5c62..00000000000 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientImpl.java +++ /dev/null @@ -1,70 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2013 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.endpoints; - -import java.util.concurrent.ConcurrentHashMap; - -import javax.websocket.ClientEndpoint; - -import org.eclipse.jetty.websocket.api.InvalidWebSocketException; -import org.eclipse.jetty.websocket.api.WebSocketPolicy; -import org.eclipse.jetty.websocket.common.events.EventDriver; -import org.eclipse.jetty.websocket.common.events.EventDriverImpl; - -/** - * {@link EventDriverImpl} for {@link ClientEndpoint @ClientEndpoint} annotated classes - */ -public class JsrAnnotatedClientImpl implements EventDriverImpl -{ - private ConcurrentHashMap, JsrAnnotatedMetadata> cache = new ConcurrentHashMap<>(); - - @Override - public EventDriver create(Object websocket, WebSocketPolicy policy) - { - Class websocketClass = websocket.getClass(); - - ClientEndpoint wsclient = websocketClass.getAnnotation(ClientEndpoint.class); - if (wsclient == null) - { - throw new InvalidWebSocketException("Cannot handle @ClientEndpoint annotations here"); - } - - JsrAnnotatedMetadata metadata = cache.get(websocketClass); - if (metadata == null) - { - JsrAnnotatedClientScanner scanner = new JsrAnnotatedClientScanner(websocketClass); - metadata = scanner.scan(); - cache.put(websocketClass,metadata); - } - - return new JsrAnnotatedClientEventDriver(policy,websocket,metadata); - } - - @Override - public String describeRule() - { - return "class annotated with @" + ClientEndpoint.class.getName(); - } - - @Override - public boolean supports(Object websocket) - { - return (websocket.getClass().getAnnotation(ClientEndpoint.class) != null); - } -} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScanner.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScanner.java deleted file mode 100644 index 523611a87ed..00000000000 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScanner.java +++ /dev/null @@ -1,217 +0,0 @@ -// -// ======================================================================== -// Copyright (c) 1995-2013 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.endpoints; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; - -import javax.websocket.ClientEndpoint; -import javax.websocket.CloseReason; -import javax.websocket.EndpointConfig; -import javax.websocket.OnClose; -import javax.websocket.OnError; -import javax.websocket.OnMessage; -import javax.websocket.OnOpen; -import javax.websocket.Session; - -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.websocket.api.InvalidWebSocketException; -import org.eclipse.jetty.websocket.common.events.ParamList; -import org.eclipse.jetty.websocket.common.events.annotated.AbstractMethodAnnotationScanner; -import org.eclipse.jetty.websocket.common.events.annotated.CallableMethod; -import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; -import org.eclipse.jetty.websocket.jsr356.decoders.Decoders; -import org.eclipse.jetty.websocket.jsr356.encoders.Encoders; -import org.eclipse.jetty.websocket.jsr356.endpoints.JsrMethodParameters.Param; - -/** - * Scanner for javax.websocket {@link WebSocketEndpoint @WebSocketEndpoint} and {@link ClientEndpoint @ClientEndpoint} annotated websockets - */ -public class JsrAnnotatedClientScanner extends AbstractMethodAnnotationScanner -{ - private static final Logger LOG = Log.getLogger(JsrAnnotatedClientScanner.class); - - private static final ParamList validOpenParams; - private static final ParamList validCloseParams; - private static final ParamList validErrorParams; - - static - { - validOpenParams = new ParamList(); - validOpenParams.addParams(Session.class); - validOpenParams.addParams(EndpointConfig.class); - - validCloseParams = new ParamList(); - validCloseParams.addParams(Session.class); - validCloseParams.addParams(CloseReason.class); - - validErrorParams = new ParamList(); - validErrorParams.addParams(Session.class); - validErrorParams.addParams(Throwable.class); - - } - - protected final Class pojo; - protected final Encoders encoders; - protected final Decoders decoders; - - public JsrAnnotatedClientScanner(Class websocket) - { - this.pojo = websocket; - - ClientEndpoint anno = websocket.getAnnotation(ClientEndpoint.class); - if (anno == null) - { - throw new InvalidWebSocketException("Unsupported WebSocket object, missing @" + ClientEndpoint.class + " annotation"); - } - - this.encoders = new Encoders(anno.encoders()); - this.decoders = new Decoders(anno.decoders()); - } - - private void assertValidJsrSignature(Method method, Class annoClass, ParamList validParams) - { - JsrMethodParameters params = new JsrMethodParameters(method); - - // First, find the path-mapping parameters - for (Param param : params) - { - String varname = getPathMappingParameterVariable(param.type); - if (varname != null) - { - param.setPathParamVariable(varname); - } - } - - // Next find the valid parameter sets and flag them - for (Class[] paramSet : validParams) - { - // Each entry in validParams is a set of possible valid references. - // If not all parts of the set are present, that set isn't valid for the provided parameters. - - if (params.containsParameterSet(paramSet)) - { - // flag as valid - params.setValid(paramSet); - } - } - - // Finally, ensure we identified all of the parameters - for (Param param : params) - { - if (param.isValid() == false) - { - StringBuilder err = new StringBuilder(); - err.append("Encountered invalid/unhandled parameter <"); - err.append(param.type.getName()); - err.append("> (position ").append(param.index).append(") in method <"); - err.append(method.getName()); - err.append("> of object <"); - err.append(pojo.getName()); - err.append("> that doesn't fit the requirements for the @"); - err.append(annoClass.getSimpleName()); - err.append(" annotation"); - - throw new InvalidSignatureException(err.toString()); - } - } - } - - public String getPathMappingParameterVariable(Class type) - { - /* override to implement */ - return null; - } - - @Override - public void onMethodAnnotation(JsrAnnotatedMetadata metadata, Class pojo, Method method, Annotation annotation) - { - LOG.debug("onMethodAnnotation({}, {}, {}, {})",metadata,pojo,method,annotation); - - if (isAnnotation(annotation,OnOpen.class)) - { - assertIsPublicNonStatic(method); - assertIsReturn(method,Void.TYPE); - assertValidJsrSignature(method,OnOpen.class,validOpenParams); - assertUnset(metadata.onOpen,OnOpen.class,method); - metadata.onOpen = new CallableMethod(pojo,method); - return; - } - - if (isAnnotation(annotation,OnClose.class)) - { - assertIsPublicNonStatic(method); - assertIsReturn(method,Void.TYPE); - assertValidJsrSignature(method,OnClose.class,validCloseParams); - assertUnset(metadata.onClose,OnClose.class,method); - metadata.onClose = new CallableMethod(pojo,method); - return; - } - - if (isAnnotation(annotation,OnError.class)) - { - assertIsPublicNonStatic(method); - assertIsReturn(method,Void.TYPE); - assertValidJsrSignature(method,OnError.class,validErrorParams); - assertUnset(metadata.onError,OnError.class,method); - metadata.onError = new CallableMethod(pojo,method); - return; - } - - if (isAnnotation(annotation,OnMessage.class)) - { - assertIsPublicNonStatic(method); - - JsrMessageCallableMethod callable = new JsrMessageCallableMethod(pojo,method,encoders,decoders); - if (callable.isTextFormat()) - { - // TEXT - assertUnset(metadata.onText,OnMessage.class,method); - metadata.onText = callable; - return; - } - - if (callable.isBinaryFormat()) - { - // BINARY - assertUnset(metadata.onBinary,OnMessage.class,method); - metadata.onBinary = callable; - return; - } - - if (callable.isPongFormat()) - { - // PONG - assertUnset(metadata.onPong,OnMessage.class,method); - metadata.onPong = callable; - return; - } - - return; - } - } - - public JsrAnnotatedMetadata scan() - { - JsrAnnotatedMetadata metadata = new JsrAnnotatedMetadata(); - scanMethodAnnotations(metadata,pojo); - return metadata; - } -} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedMetadata.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedMetadata.java index 7f5eed11db8..335a076dad3 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedMetadata.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedMetadata.java @@ -18,38 +18,52 @@ package org.eclipse.jetty.websocket.jsr356.endpoints; +import java.lang.annotation.Annotation; + import javax.websocket.OnClose; import javax.websocket.OnError; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import org.eclipse.jetty.websocket.common.events.annotated.CallableMethod; +import org.eclipse.jetty.websocket.jsr356.decoders.Decoders; +import org.eclipse.jetty.websocket.jsr356.encoders.Encoders; /** * Represents the metadata associated with Annotation discovery of a specific class. */ public class JsrAnnotatedMetadata { + public Class pojo; + public Class classAnnotation; + public Decoders decoders; + public Encoders encoders; + /** * Callable for @{@link OnOpen} annotation */ public CallableMethod onOpen; + /** * Callable for @{@link OnClose} annotation */ public CallableMethod onClose; + /** * Callable for @{@link OnError} annotation */ public CallableMethod onError; + /** * Callable for @{@link OnMessage} annotation dealing with Text Message Format */ public CallableMethod onText; + /** * Callable for @{@link OnMessage} annotation dealing with Binary Message Format */ public CallableMethod onBinary; + /** * Callable for @{@link OnMessage} annotation dealing with Pong Message Format */ diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrClientMetadata.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrClientMetadata.java new file mode 100644 index 00000000000..72af46b786d --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrClientMetadata.java @@ -0,0 +1,82 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.endpoints; + +import java.util.LinkedList; + +import javax.websocket.ClientEndpoint; +import javax.websocket.Decoder; + +import org.eclipse.jetty.websocket.api.InvalidWebSocketException; +import org.eclipse.jetty.websocket.jsr356.annotations.IJsrParamId; +import org.eclipse.jetty.websocket.jsr356.annotations.JsrMetadata; +import org.eclipse.jetty.websocket.jsr356.annotations.JsrParamIdBinaryDecoder; +import org.eclipse.jetty.websocket.jsr356.annotations.JsrParamIdTextDecoder; +import org.eclipse.jetty.websocket.jsr356.decoders.Decoders; +import org.eclipse.jetty.websocket.jsr356.decoders.Decoders.DecoderRef; +import org.eclipse.jetty.websocket.jsr356.encoders.Encoders; + +public class JsrClientMetadata extends JsrMetadata +{ + private final ClientEndpoint endpoint; + + public JsrClientMetadata(Class websocket) + { + super(websocket); + + ClientEndpoint anno = websocket.getAnnotation(ClientEndpoint.class); + if (anno == null) + { + throw new InvalidWebSocketException("Unsupported WebSocket object, missing @" + ClientEndpoint.class + " annotation"); + } + + this.endpoint = anno; + this.encoders = new Encoders(anno.encoders()); + this.decoders = new Decoders(anno.decoders()); + } + + @Override + public void customizeParamsOnMessage(LinkedList params) + { + for (DecoderRef ref : decoders) + { + Class decoder = ref.getDecoder(); + + if (Decoder.Text.class.isAssignableFrom(decoder) || Decoder.TextStream.class.isAssignableFrom(decoder)) + { + params.add(new JsrParamIdTextDecoder(ref)); + continue; + } + + if (Decoder.Binary.class.isAssignableFrom(decoder) || Decoder.BinaryStream.class.isAssignableFrom(decoder)) + { + params.add(new JsrParamIdBinaryDecoder(ref)); + continue; + } + + throw new IllegalStateException("Invalid Decoder: " + decoder); + } + } + + @Override + public ClientEndpoint getAnnotation() + { + return endpoint; + } +} diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEndpointEventDriver.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEndpointEventDriver.java index 69a9cbc23af..67ee9ea7bfd 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEndpointEventDriver.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEndpointEventDriver.java @@ -30,6 +30,19 @@ import org.eclipse.jetty.websocket.common.events.EventDriver; public class JsrEndpointEventDriver implements EventDriver { + @Override + public WebSocketPolicy getPolicy() + { + // TODO Auto-generated method stub + return null; + } + + @Override + public WebSocketSession getSession() + { + // TODO Auto-generated method stub + return null; + } @Override public void incomingError(WebSocketException e) @@ -45,20 +58,6 @@ public class JsrEndpointEventDriver implements EventDriver } - @Override - public WebSocketPolicy getPolicy() - { - // TODO Auto-generated method stub - return null; - } - - @Override - public WebSocketSession getSession() - { - // TODO Auto-generated method stub - return null; - } - @Override public void onBinaryFrame(ByteBuffer buffer, boolean fin) throws IOException { @@ -121,5 +120,4 @@ public class JsrEndpointEventDriver implements EventDriver // TODO Auto-generated method stub } - } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScannerTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/ClientAnnotatedEndpointScannerTest.java similarity index 81% rename from jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScannerTest.java rename to jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/ClientAnnotatedEndpointScannerTest.java index 1d4cfbda501..6d5181b8490 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScannerTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/ClientAnnotatedEndpointScannerTest.java @@ -23,12 +23,13 @@ import static org.hamcrest.Matchers.*; import javax.websocket.CloseReason; import org.eclipse.jetty.websocket.common.events.annotated.CallableMethod; +import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner; import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicOpenCloseSessionSocket; import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicOpenCloseSocket; import org.junit.Assert; import org.junit.Test; -public class JsrAnnotatedClientScannerTest +public class ClientAnnotatedEndpointScannerTest { private void assertHasCallable(String msg, CallableMethod callable, Class... expectedParameters) { @@ -46,8 +47,9 @@ public class JsrAnnotatedClientScannerTest @Test public void testScan_BasicOpenClose() { - JsrAnnotatedClientScanner scanner = new JsrAnnotatedClientScanner(BasicOpenCloseSocket.class); - JsrAnnotatedMetadata metadata = scanner.scan(); + JsrClientMetadata metadata = new JsrClientMetadata(BasicOpenCloseSocket.class); + AnnotatedEndpointScanner scanner = new AnnotatedEndpointScanner(metadata); + scanner.scan(); Assert.assertThat("Metadata",metadata,notNullValue()); @@ -58,8 +60,9 @@ public class JsrAnnotatedClientScannerTest @Test public void testScan_BasicSessionOpenClose() { - JsrAnnotatedClientScanner scanner = new JsrAnnotatedClientScanner(BasicOpenCloseSessionSocket.class); - JsrAnnotatedMetadata metadata = scanner.scan(); + JsrClientMetadata metadata = new JsrClientMetadata(BasicOpenCloseSessionSocket.class); + AnnotatedEndpointScanner scanner = new AnnotatedEndpointScanner(metadata); + scanner.scan(); Assert.assertThat("Metadata",metadata,notNullValue()); diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScanner_GoodSignaturesTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/ClientAnnotatedEndpointScanner_GoodSignaturesTest.java similarity index 85% rename from jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScanner_GoodSignaturesTest.java rename to jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/ClientAnnotatedEndpointScanner_GoodSignaturesTest.java index 2c1e6e09823..dbdfe18f27d 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScanner_GoodSignaturesTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/ClientAnnotatedEndpointScanner_GoodSignaturesTest.java @@ -30,7 +30,9 @@ import javax.websocket.CloseReason; import javax.websocket.PongMessage; import javax.websocket.Session; -import org.eclipse.jetty.websocket.common.events.annotated.CallableMethod; +import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner; +import org.eclipse.jetty.websocket.jsr356.annotations.JsrMetadata; +import org.eclipse.jetty.websocket.jsr356.annotations.ParameterizedMethod; import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicBinaryMessageByteBufferSocket; import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicCloseReasonSessionSocket; import org.eclipse.jetty.websocket.jsr356.endpoints.samples.BasicCloseReasonSocket; @@ -55,7 +57,7 @@ import org.junit.runners.Parameterized.Parameters; * Test {@link JsrAnnotatedClientScanner} against various valid, simple, 1 method annotated classes with valid signatures. */ @RunWith(Parameterized.class) -public class JsrAnnotatedClientScanner_GoodSignaturesTest +public class ClientAnnotatedEndpointScanner_GoodSignaturesTest { public static class Case { @@ -84,12 +86,12 @@ public class JsrAnnotatedClientScanner_GoodSignaturesTest public static Collection data() throws Exception { List data = new ArrayList<>(); - Field fOpen = findFieldRef(JsrAnnotatedMetadata.class,"onOpen"); - Field fClose = findFieldRef(JsrAnnotatedMetadata.class,"onClose"); - Field fError = findFieldRef(JsrAnnotatedMetadata.class,"onError"); - Field fText = findFieldRef(JsrAnnotatedMetadata.class,"onText"); - Field fBinary = findFieldRef(JsrAnnotatedMetadata.class,"onBinary"); - Field fPong = findFieldRef(JsrAnnotatedMetadata.class,"onPong"); + Field fOpen = findFieldRef(JsrMetadata.class,"onOpen"); + Field fClose = findFieldRef(JsrMetadata.class,"onClose"); + Field fError = findFieldRef(JsrMetadata.class,"onError"); + Field fText = findFieldRef(JsrMetadata.class,"onText"); + Field fBinary = findFieldRef(JsrMetadata.class,"onBinary"); + Field fPong = findFieldRef(JsrMetadata.class,"onPong"); // @formatter:off // -- Open Events @@ -126,7 +128,7 @@ public class JsrAnnotatedClientScanner_GoodSignaturesTest private Case testcase; - public JsrAnnotatedClientScanner_GoodSignaturesTest(Case testcase) + public ClientAnnotatedEndpointScanner_GoodSignaturesTest(Case testcase) { this.testcase = testcase; } @@ -134,12 +136,13 @@ public class JsrAnnotatedClientScanner_GoodSignaturesTest @Test public void testScan_Basic() throws Exception { - JsrAnnotatedClientScanner scanner = new JsrAnnotatedClientScanner(testcase.pojo); - JsrAnnotatedMetadata metadata = scanner.scan(); + JsrClientMetadata metadata = new JsrClientMetadata(testcase.pojo); + AnnotatedEndpointScanner scanner = new AnnotatedEndpointScanner(metadata); + scanner.scan(); Assert.assertThat("Metadata",metadata,notNullValue()); - CallableMethod cm = (CallableMethod)testcase.metadataField.get(metadata); + ParameterizedMethod cm = (ParameterizedMethod)testcase.metadataField.get(metadata); Assert.assertThat(testcase.metadataField.toString(),cm,notNullValue()); int len = testcase.expectedParameters.length; for (int i = 0; i < len; i++) diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScanner_InvalidSignaturesTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/ClientAnnotatedEndpointScanner_InvalidSignaturesTest.java similarity index 87% rename from jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScanner_InvalidSignaturesTest.java rename to jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/ClientAnnotatedEndpointScanner_InvalidSignaturesTest.java index 2176f2ba07a..6dc5cfba4a5 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedClientScanner_InvalidSignaturesTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/ClientAnnotatedEndpointScanner_InvalidSignaturesTest.java @@ -32,6 +32,7 @@ import javax.websocket.OnOpen; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; +import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner; import org.eclipse.jetty.websocket.jsr356.endpoints.samples.InvalidCloseIntSocket; import org.eclipse.jetty.websocket.jsr356.endpoints.samples.InvalidErrorErrorSocket; import org.eclipse.jetty.websocket.jsr356.endpoints.samples.InvalidErrorExceptionSocket; @@ -49,9 +50,9 @@ import org.junit.runners.Parameterized.Parameters; * Test {@link JsrAnnotatedClientScanner} against various simple, single method annotated classes with invalid signatures. */ @RunWith(Parameterized.class) -public class JsrAnnotatedClientScanner_InvalidSignaturesTest +public class ClientAnnotatedEndpointScanner_InvalidSignaturesTest { - private static final Logger LOG = Log.getLogger(JsrAnnotatedClientScanner_InvalidSignaturesTest.class); + private static final Logger LOG = Log.getLogger(ClientAnnotatedEndpointScanner_InvalidSignaturesTest.class); @Parameters public static Collection[]> data() @@ -81,7 +82,7 @@ public class JsrAnnotatedClientScanner_InvalidSignaturesTest // The annotation class expected to be mentioned in the error message private Class expectedAnnoClass; - public JsrAnnotatedClientScanner_InvalidSignaturesTest(Class pojo, Class expectedAnnotation) + public ClientAnnotatedEndpointScanner_InvalidSignaturesTest(Class pojo, Class expectedAnnotation) { this.pojo = pojo; this.expectedAnnoClass = expectedAnnotation; @@ -90,7 +91,8 @@ public class JsrAnnotatedClientScanner_InvalidSignaturesTest @Test public void testScan_InvalidSignature() { - JsrAnnotatedClientScanner scanner = new JsrAnnotatedClientScanner(pojo); + JsrClientMetadata metadata = new JsrClientMetadata(pojo); + AnnotatedEndpointScanner scanner = new AnnotatedEndpointScanner(metadata); try { scanner.scan(); diff --git a/jetty-websocket/javax-websocket-server-impl/pom.xml b/jetty-websocket/javax-websocket-server-impl/pom.xml index 282ef0d188d..5405430effb 100644 --- a/jetty-websocket/javax-websocket-server-impl/pom.xml +++ b/jetty-websocket/javax-websocket-server-impl/pom.xml @@ -16,6 +16,11 @@ + + org.eclipse.jetty + jetty-annotations + ${project.version} + org.eclipse.jetty.websocket javax-websocket-client-impl diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrParamPath.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrParamPath.java new file mode 100644 index 00000000000..46f87d26ee8 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrParamPath.java @@ -0,0 +1,42 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server; + +import javax.websocket.server.PathParam; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; +import org.eclipse.jetty.websocket.jsr356.annotations.IJsrMethod; +import org.eclipse.jetty.websocket.jsr356.annotations.IJsrParamId; +import org.eclipse.jetty.websocket.jsr356.annotations.JsrMetadata; + +/** + * Param handling for static parameters annotated with @{@link PathParam} + */ +public class JsrParamPath implements IJsrParamId +{ + public static final IJsrParamId INSTANCE = new JsrParamPath(); + + @Override + public boolean process(Class type, IJsrMethod method, JsrMetadata metadata) throws InvalidSignatureException + { + PathParam pathparam = type.getAnnotation(PathParam.class); + + return false; + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerMessageCallableMethod.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerMessageCallableMethod.java new file mode 100644 index 00000000000..ba3dbb60c37 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerMessageCallableMethod.java @@ -0,0 +1,47 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server; + +import java.lang.reflect.Method; + +import javax.websocket.server.PathParam; + +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; +import org.eclipse.jetty.websocket.jsr356.decoders.Decoders; +import org.eclipse.jetty.websocket.jsr356.encoders.Encoders; +import org.eclipse.jetty.websocket.jsr356.endpoints.JsrMessageCallableMethod; + +public class JsrServerMessageCallableMethod extends JsrMessageCallableMethod +{ + public JsrServerMessageCallableMethod(Class pojo, Method method, Encoders encoders, Decoders decoders) throws InvalidSignatureException + { + super(pojo,method,encoders,decoders); + } + + @Override + public String getPathParam(Class paramType) + { + PathParam pathParam = paramType.getAnnotation(PathParam.class); + if (pathParam == null) + { + return null; + } + return pathParam.value(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerMetadata.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerMetadata.java new file mode 100644 index 00000000000..a11f5ba9a61 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrServerMetadata.java @@ -0,0 +1,101 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server; + +import java.util.LinkedList; + +import javax.websocket.Decoder; +import javax.websocket.server.ServerEndpoint; + +import org.eclipse.jetty.websocket.api.InvalidWebSocketException; +import org.eclipse.jetty.websocket.jsr356.annotations.IJsrParamId; +import org.eclipse.jetty.websocket.jsr356.annotations.JsrMetadata; +import org.eclipse.jetty.websocket.jsr356.annotations.JsrParamIdBinaryDecoder; +import org.eclipse.jetty.websocket.jsr356.annotations.JsrParamIdTextDecoder; +import org.eclipse.jetty.websocket.jsr356.decoders.Decoders; +import org.eclipse.jetty.websocket.jsr356.decoders.Decoders.DecoderRef; +import org.eclipse.jetty.websocket.jsr356.encoders.Encoders; + +public class JsrServerMetadata extends JsrMetadata +{ + private final ServerEndpoint endpoint; + + protected JsrServerMetadata(Class websocket) + { + super(websocket); + + ServerEndpoint anno = websocket.getAnnotation(ServerEndpoint.class); + if (anno == null) + { + throw new InvalidWebSocketException("Unsupported WebSocket object, missing @" + ServerEndpoint.class + " annotation"); + } + + this.endpoint = anno; + this.encoders = new Encoders(anno.encoders()); + this.decoders = new Decoders(anno.decoders()); + } + + @Override + public ServerEndpoint getAnnotation() + { + return endpoint; + } + + @Override + public void customizeParamsOnClose(LinkedList params) + { + params.addFirst(JsrParamPath.INSTANCE); + } + + @Override + public void customizeParamsOnError(LinkedList params) + { + params.addFirst(JsrParamPath.INSTANCE); + } + + @Override + public void customizeParamsOnOpen(LinkedList params) + { + params.addFirst(JsrParamPath.INSTANCE); + } + + @Override + public void customizeParamsOnMessage(LinkedList params) + { + for (DecoderRef ref : decoders) + { + Class decoder = ref.getDecoder(); + + if (Decoder.Text.class.isAssignableFrom(decoder) || Decoder.TextStream.class.isAssignableFrom(decoder)) + { + params.add(new JsrParamIdTextDecoder(ref)); + continue; + } + + if (Decoder.Binary.class.isAssignableFrom(decoder) || Decoder.BinaryStream.class.isAssignableFrom(decoder)) + { + params.add(new JsrParamIdBinaryDecoder(ref)); + continue; + } + + throw new IllegalStateException("Invalid Decoder: " + decoder); + } + params.addFirst(JsrParamPath.INSTANCE); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerEndpointAnnotation.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerEndpointAnnotation.java new file mode 100644 index 00000000000..a739fbc6210 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerEndpointAnnotation.java @@ -0,0 +1,61 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server; + +import javax.websocket.server.ServerEndpoint; + +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.webapp.DiscoveredAnnotation; +import org.eclipse.jetty.webapp.WebAppContext; + +public class ServerEndpointAnnotation extends DiscoveredAnnotation +{ + private static final Logger LOG = Log.getLogger(ServerEndpointAnnotation.class); + + public ServerEndpointAnnotation(WebAppContext context, String className, Resource resource) + { + super(context,className,resource); + } + + public ServerEndpointAnnotation(WebAppContext context, String className) + { + super(context,className); + } + + @Override + public void apply() + { + Class clazz = getTargetClass(); + + if (clazz == null) + { + LOG.warn(_className+" cannot be loaded"); + return; + } + + ServerEndpoint annotation = clazz.getAnnotation(ServerEndpoint.class); + + String path = annotation.value(); + + // TODO: scan class for annotated methods + // TODO: add new websocket endpoint to _context with path mapping + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerEndpointAnnotationHandler.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerEndpointAnnotationHandler.java new file mode 100644 index 00000000000..8812aa2f2f9 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/ServerEndpointAnnotationHandler.java @@ -0,0 +1,84 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server; + +import java.util.List; + +import javax.websocket.server.ServerEndpoint; + +import org.eclipse.jetty.annotations.AbstractDiscoverableAnnotationHandler; +import org.eclipse.jetty.annotations.AnnotationParser.Value; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.webapp.DiscoveredAnnotation; +import org.eclipse.jetty.webapp.WebAppContext; + +/** + * Processing for @{@link ServerEndpoint} annotations during Web App Annotation Scanning + */ +public class ServerEndpointAnnotationHandler extends AbstractDiscoverableAnnotationHandler +{ + private static final String ANNOTATION_NAME = "javax.websocket.server.ServerEndpoint"; + private static final Logger LOG = Log.getLogger(ServerEndpointAnnotationHandler.class); + + public ServerEndpointAnnotationHandler(WebAppContext context, List list) + { + super(context,list); + } + + public ServerEndpointAnnotationHandler(WebAppContext context) + { + super(context); + } + + @Override + public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotationName, + List values) + { + if (!ANNOTATION_NAME.equals(annotationName)) + { + // Not the one we are interested in + return; + } + + ServerEndpointAnnotation annotation = new ServerEndpointAnnotation(_context,className,_resource); + addAnnotation(annotation); + } + + @Override + public void handleMethod(String className, String methodName, int access, String desc, String signature, String[] exceptions, String annotation, + List values) + { + LOG.warn("@WebServlet annotation not supported for methods"); + } + + @Override + public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation, + List values) + { + LOG.warn("@WebServlet annotation not supported for fields"); + } + + @Override + public String getAnnotationName() + { + return ANNOTATION_NAME; + } + +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScannerTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScannerTest.java new file mode 100644 index 00000000000..f7ed2a1d948 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScannerTest.java @@ -0,0 +1,32 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class ServerAnnotatedEndpointScannerTest +{ + @Test + public void test() + { + fail("Not yet implemented"); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_GoodSignaturesTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_GoodSignaturesTest.java new file mode 100644 index 00000000000..20df13b4e32 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_GoodSignaturesTest.java @@ -0,0 +1,156 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server; + +import static org.hamcrest.Matchers.*; + +import java.lang.reflect.Field; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.websocket.CloseReason; +import javax.websocket.PongMessage; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.common.events.annotated.CallableMethod; +import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner; +import org.eclipse.jetty.websocket.jsr356.endpoints.JsrAnnotatedMetadata; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicBinaryMessageByteBufferSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseReasonSessionSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseReasonSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseSessionReasonSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicCloseSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorSessionSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorSessionThrowableSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorThrowableSessionSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicErrorThrowableSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicOpenSessionSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicOpenSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicPongMessageSocket; +import org.eclipse.jetty.websocket.jsr356.server.samples.BasicTextMessageStringSocket; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * Test {@link JsrAnnotatedServerScanner} against various valid, simple, 1 method annotated classes with valid signatures. + */ +@RunWith(Parameterized.class) +public class ServerAnnotatedEndpointScanner_GoodSignaturesTest +{ + public static class Case + { + public static void add(List data, Class pojo, Field metadataField, Class... expectedParams) + { + data.add(new Case[] + { new Case(pojo,metadataField,expectedParams) }); + } + + // The websocket pojo to test against + Class pojo; + // The JsrAnnotatedMetadata field that should be populated + Field metadataField; + // The expected parameters for the Callable found by the scanner + Class expectedParameters[]; + + public Case(Class pojo, Field metadataField, Class... expectedParams) + { + this.pojo = pojo; + this.metadataField = metadataField; + this.expectedParameters = expectedParams; + } + } + + @Parameters + public static Collection data() throws Exception + { + List data = new ArrayList<>(); + Field fOpen = findFieldRef(JsrAnnotatedMetadata.class,"onOpen"); + Field fClose = findFieldRef(JsrAnnotatedMetadata.class,"onClose"); + Field fError = findFieldRef(JsrAnnotatedMetadata.class,"onError"); + Field fText = findFieldRef(JsrAnnotatedMetadata.class,"onText"); + Field fBinary = findFieldRef(JsrAnnotatedMetadata.class,"onBinary"); + Field fPong = findFieldRef(JsrAnnotatedMetadata.class,"onPong"); + + // @formatter:off + // -- Open Events + Case.add(data, BasicOpenSocket.class, fOpen); + Case.add(data, BasicOpenSessionSocket.class, fOpen, Session.class); + // -- Close Events + Case.add(data, BasicCloseSocket.class, fClose); + Case.add(data, BasicCloseReasonSocket.class, fClose, CloseReason.class); + Case.add(data, BasicCloseReasonSessionSocket.class, fClose, CloseReason.class, Session.class); + Case.add(data, BasicCloseSessionReasonSocket.class, fClose, Session.class, CloseReason.class); + // -- Error Events + Case.add(data, BasicErrorSocket.class, fError); + Case.add(data, BasicErrorSessionSocket.class, fError, Session.class); + Case.add(data, BasicErrorSessionThrowableSocket.class, fError, Session.class, Throwable.class); + Case.add(data, BasicErrorThrowableSocket.class, fError, Throwable.class); + Case.add(data, BasicErrorThrowableSessionSocket.class, fError, Throwable.class, Session.class); + // -- Text Events + Case.add(data, BasicTextMessageStringSocket.class, fText, String.class); + // -- Binary Events + Case.add(data, BasicBinaryMessageByteBufferSocket.class, fBinary, ByteBuffer.class); + // -- Pong Events + Case.add(data, BasicPongMessageSocket.class, fPong, PongMessage.class); + // @formatter:on + + // TODO: validate return types + + return data; + } + + private static Field findFieldRef(Class clazz, String fldName) throws Exception + { + return clazz.getField(fldName); + } + + private Case testcase; + + public ServerAnnotatedEndpointScanner_GoodSignaturesTest(Case testcase) + { + this.testcase = testcase; + } + + @Test + public void testScan_Basic() throws Exception + { + JsrServerMetadata metadata = new JsrServerMetadata(testcase.pojo); + AnnotatedEndpointScanner scanner = new AnnotatedEndpointScanner(metadata); + scanner.scan(); + + Assert.assertThat("Metadata",metadata,notNullValue()); + + CallableMethod cm = (CallableMethod)testcase.metadataField.get(metadata); + Assert.assertThat(testcase.metadataField.toString(),cm,notNullValue()); + int len = testcase.expectedParameters.length; + for (int i = 0; i < len; i++) + { + Class expectedParam = testcase.expectedParameters[i]; + Class actualParam = cm.getParamTypes()[i]; + + Assert.assertTrue("Parameter[" + i + "] - expected:[" + expectedParam + "], actual:[" + actualParam + "]",actualParam.equals(expectedParam)); + } + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_InvalidSignaturesTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_InvalidSignaturesTest.java new file mode 100644 index 00000000000..0a51fe990aa --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_InvalidSignaturesTest.java @@ -0,0 +1,108 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server; + +import static org.hamcrest.Matchers.*; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.websocket.OnClose; +import javax.websocket.OnError; +import javax.websocket.OnOpen; + +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException; +import org.eclipse.jetty.websocket.jsr356.annotations.AnnotatedEndpointScanner; +import org.eclipse.jetty.websocket.jsr356.endpoints.samples.InvalidCloseIntSocket; +import org.eclipse.jetty.websocket.jsr356.endpoints.samples.InvalidErrorErrorSocket; +import org.eclipse.jetty.websocket.jsr356.endpoints.samples.InvalidErrorExceptionSocket; +import org.eclipse.jetty.websocket.jsr356.endpoints.samples.InvalidErrorIntSocket; +import org.eclipse.jetty.websocket.jsr356.endpoints.samples.InvalidOpenCloseReasonSocket; +import org.eclipse.jetty.websocket.jsr356.endpoints.samples.InvalidOpenIntSocket; +import org.eclipse.jetty.websocket.jsr356.endpoints.samples.InvalidOpenSessionIntSocket; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +/** + * Test {@link JsrAnnotatedServerScanner} against various simple, single method annotated classes with invalid signatures. + */ +@RunWith(Parameterized.class) +public class ServerAnnotatedEndpointScanner_InvalidSignaturesTest +{ + private static final Logger LOG = Log.getLogger(ServerAnnotatedEndpointScanner_InvalidSignaturesTest.class); + + @Parameters + public static Collection[]> data() + { + List[]> data = new ArrayList<>(); + + // @formatter:off + data.add(new Class[]{ InvalidCloseIntSocket.class, OnClose.class }); + data.add(new Class[]{ InvalidErrorErrorSocket.class, OnError.class }); + data.add(new Class[]{ InvalidErrorExceptionSocket.class, OnError.class }); + data.add(new Class[]{ InvalidErrorIntSocket.class, OnError.class }); + data.add(new Class[]{ InvalidOpenCloseReasonSocket.class, OnOpen.class }); + data.add(new Class[]{ InvalidOpenIntSocket.class, OnOpen.class }); + data.add(new Class[]{ InvalidOpenSessionIntSocket.class, OnOpen.class }); + // @formatter:on + + // TODO: invalid return types + // TODO: static methods + // TODO: private or protected methods + // TODO: abstract methods + + return data; + } + + // The pojo to test + private Class pojo; + // The annotation class expected to be mentioned in the error message + private Class expectedAnnoClass; + + public ServerAnnotatedEndpointScanner_InvalidSignaturesTest(Class pojo, Class expectedAnnotation) + { + this.pojo = pojo; + this.expectedAnnoClass = expectedAnnotation; + } + + @Test + public void testScan_InvalidSignature() + { + JsrServerMetadata metadata = new JsrServerMetadata(pojo); + AnnotatedEndpointScanner scanner = new AnnotatedEndpointScanner(metadata); + + try + { + scanner.scan(); + Assert.fail("Expected " + InvalidSignatureException.class + " with message that references " + expectedAnnoClass + " annotation"); + } + catch (InvalidSignatureException e) + { + LOG.debug("{}:{}",e.getClass(),e.getMessage()); + Assert.assertThat("Message",e.getMessage(),containsString(expectedAnnoClass.getSimpleName())); + } + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/TrackingSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/TrackingSocket.java new file mode 100644 index 00000000000..1e2c8e1c785 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/TrackingSocket.java @@ -0,0 +1,125 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server; + +import static org.hamcrest.Matchers.*; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.websocket.CloseReason; +import javax.websocket.CloseReason.CloseCode; + +import org.eclipse.jetty.util.BlockingArrayQueue; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.junit.Assert; + +/** + * Abstract base socket used for tracking state and events within the socket for testing reasons. + */ +public abstract class TrackingSocket +{ + private static final Logger LOG = Log.getLogger(TrackingSocket.class); + + public CloseReason closeReason; + public BlockingQueue eventQueue = new BlockingArrayQueue(); + public BlockingQueue errorQueue = new BlockingArrayQueue<>(); + public CountDownLatch openLatch = new CountDownLatch(1); + public CountDownLatch closeLatch = new CountDownLatch(1); + public CountDownLatch dataLatch = new CountDownLatch(1); + + public void assertClose(CloseCode expectedCode, String expectedReason) throws InterruptedException + { + assertCloseCode(expectedCode); + assertCloseReason(expectedReason); + } + + public void assertCloseCode(CloseCode expectedCode) throws InterruptedException + { + Assert.assertThat("Was Closed",closeLatch.await(50,TimeUnit.MILLISECONDS),is(true)); + Assert.assertThat("CloseReason",closeReason,notNullValue()); + Assert.assertThat("Close Code",closeReason.getCloseCode(),is(expectedCode)); + } + + private void assertCloseReason(String expectedReason) + { + Assert.assertThat("Close Reason",closeReason.getReasonPhrase(),is(expectedReason)); + } + + protected void addEvent(String format, Object... args) + { + eventQueue.add(String.format(format,args)); + } + + protected void addError(Throwable t) + { + errorQueue.add(t); + } + + public void assertIsOpen() throws InterruptedException + { + assertWasOpened(); + assertNotClosed(); + } + + public void assertEvent(String expected) + { + String actual = eventQueue.poll(); + Assert.assertEquals("Event",expected,actual); + } + + public void assertNotClosed() + { + Assert.assertThat("Closed Latch",closeLatch.getCount(),greaterThanOrEqualTo(1L)); + } + + public void assertNotOpened() + { + Assert.assertThat("Open Latch",openLatch.getCount(),greaterThanOrEqualTo(1L)); + } + + public void assertWasOpened() throws InterruptedException + { + Assert.assertThat("Was Opened",openLatch.await(500,TimeUnit.MILLISECONDS),is(true)); + } + + public void clear() + { + eventQueue.clear(); + errorQueue.clear(); + } + + public void waitForClose(int timeoutDuration, TimeUnit timeoutUnit) throws InterruptedException + { + Assert.assertThat("Client Socket Closed",closeLatch.await(timeoutDuration,timeoutUnit),is(true)); + } + + public void waitForConnected(int timeoutDuration, TimeUnit timeoutUnit) throws InterruptedException + { + Assert.assertThat("Client Socket Connected",openLatch.await(timeoutDuration,timeoutUnit),is(true)); + } + + public void waitForData(int timeoutDuration, TimeUnit timeoutUnit) throws InterruptedException + { + LOG.debug("Waiting for message"); + Assert.assertThat("Data Received",dataLatch.await(timeoutDuration,timeoutUnit),is(true)); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicBinaryMessageByteBufferSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicBinaryMessageByteBufferSocket.java new file mode 100644 index 00000000000..016aba37f3e --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicBinaryMessageByteBufferSocket.java @@ -0,0 +1,37 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import java.nio.ByteBuffer; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnMessage; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicBinaryMessageByteBufferSocket extends TrackingSocket +{ + @OnMessage + public void onBinary(ByteBuffer data) + { + addEvent("onBinary(%s)",data); + dataLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseReasonSessionSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseReasonSessionSocket.java new file mode 100644 index 00000000000..4fb0f6a74d1 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseReasonSessionSocket.java @@ -0,0 +1,37 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.CloseReason; +import javax.websocket.OnClose; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicCloseReasonSessionSocket extends TrackingSocket +{ + @OnClose + public void onClose(CloseReason reason, Session session) + { + addEvent("onClose(%s,%s)",reason,session); + closeLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseReasonSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseReasonSocket.java new file mode 100644 index 00000000000..0efc0df0e70 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseReasonSocket.java @@ -0,0 +1,36 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.CloseReason; +import javax.websocket.OnClose; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicCloseReasonSocket extends TrackingSocket +{ + @OnClose + public void onClose(CloseReason reason) + { + addEvent("onClose(%s)", reason); + closeLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseSessionReasonSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseSessionReasonSocket.java new file mode 100644 index 00000000000..4276c2712c5 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseSessionReasonSocket.java @@ -0,0 +1,37 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.CloseReason; +import javax.websocket.OnClose; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicCloseSessionReasonSocket extends TrackingSocket +{ + @OnClose + public void onClose(Session session, CloseReason reason) + { + addEvent("onClose(%s,%s)",session,reason); + closeLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseSocket.java new file mode 100644 index 00000000000..9a4979b5409 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicCloseSocket.java @@ -0,0 +1,35 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnClose; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicCloseSocket extends TrackingSocket +{ + @OnClose + public void onClose() + { + addEvent("onClose()"); + closeLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorSessionSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorSessionSocket.java new file mode 100644 index 00000000000..72128d9d755 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorSessionSocket.java @@ -0,0 +1,35 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnError; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicErrorSessionSocket extends TrackingSocket +{ + @OnError + public void onError(Session session) + { + addEvent("onError(%s)",session); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorSessionThrowableSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorSessionThrowableSocket.java new file mode 100644 index 00000000000..14aa6f7bd0e --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorSessionThrowableSocket.java @@ -0,0 +1,36 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnError; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicErrorSessionThrowableSocket extends TrackingSocket +{ + @OnError + public void onError(Session session, Throwable t) + { + addEvent("onError(%s,%s)",session,t); + addError(t); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorSocket.java new file mode 100644 index 00000000000..ad7ecbe7555 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorSocket.java @@ -0,0 +1,34 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnError; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicErrorSocket extends TrackingSocket +{ + @OnError + public void onError() + { + addEvent("onError()"); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorThrowableSessionSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorThrowableSessionSocket.java new file mode 100644 index 00000000000..9ec79615c29 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorThrowableSessionSocket.java @@ -0,0 +1,36 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnError; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicErrorThrowableSessionSocket extends TrackingSocket +{ + @OnError + public void onError(Throwable t, Session session) + { + addEvent("onError(%s,%s)",t,session); + addError(t); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorThrowableSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorThrowableSocket.java new file mode 100644 index 00000000000..bf54b3ba12c --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicErrorThrowableSocket.java @@ -0,0 +1,35 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnError; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicErrorThrowableSocket extends TrackingSocket +{ + @OnError + public void onError(Throwable t) + { + addEvent("onError(%s)",t); + addError(t); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenCloseSessionSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenCloseSessionSocket.java new file mode 100644 index 00000000000..57b6bcdb248 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenCloseSessionSocket.java @@ -0,0 +1,46 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.CloseReason; +import javax.websocket.OnClose; +import javax.websocket.OnOpen; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicOpenCloseSessionSocket extends TrackingSocket +{ + @OnClose + public void onClose(CloseReason close, Session session) + { + addEvent("onClose(%s, %s)",close,session); + this.closeReason = close; + closeLatch.countDown(); + } + + @OnOpen + public void onOpen(Session session) + { + addEvent("onOpen(%s)",session); + openLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenCloseSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenCloseSocket.java new file mode 100644 index 00000000000..bce3b3fd2d2 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenCloseSocket.java @@ -0,0 +1,41 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.CloseReason; +import javax.websocket.OnClose; +import javax.websocket.OnOpen; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicOpenCloseSocket extends TrackingSocket +{ + @OnOpen + public void onOpen() { + openLatch.countDown(); + } + + @OnClose + public void onClose(CloseReason close) { + this.closeReason = close; + closeLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenSessionSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenSessionSocket.java new file mode 100644 index 00000000000..7a52491d3d6 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenSessionSocket.java @@ -0,0 +1,35 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnOpen; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicOpenSessionSocket extends TrackingSocket +{ + @OnOpen + public void onOpen(Session session) + { + openLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenSocket.java new file mode 100644 index 00000000000..57b4c0c4425 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicOpenSocket.java @@ -0,0 +1,34 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnOpen; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicOpenSocket extends TrackingSocket +{ + @OnOpen + public void onOpen() + { + openLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicPongMessageSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicPongMessageSocket.java new file mode 100644 index 00000000000..ee4a4dbf619 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicPongMessageSocket.java @@ -0,0 +1,36 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnMessage; +import javax.websocket.PongMessage; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicPongMessageSocket extends TrackingSocket +{ + @OnMessage + public void onPong(PongMessage pong) + { + addEvent("onPong(%s)",pong); + dataLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicTextMessageStringSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicTextMessageStringSocket.java new file mode 100644 index 00000000000..cd4d15dab11 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/BasicTextMessageStringSocket.java @@ -0,0 +1,35 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnMessage; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class BasicTextMessageStringSocket extends TrackingSocket +{ + @OnMessage + public void onText(String message) + { + addEvent("onText(%s)",message); + dataLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidCloseIntSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidCloseIntSocket.java new file mode 100644 index 00000000000..7df55ea8fed --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidCloseIntSocket.java @@ -0,0 +1,37 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnClose; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class InvalidCloseIntSocket extends TrackingSocket +{ + /** + * Invalid Close Method Declaration (parameter type int) + */ + @OnClose + public void onClose(int statusCode) + { + closeLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidErrorErrorSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidErrorErrorSocket.java new file mode 100644 index 00000000000..b4ab5da4804 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidErrorErrorSocket.java @@ -0,0 +1,37 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnError; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class InvalidErrorErrorSocket extends TrackingSocket +{ + /** + * Invalid Error Method Declaration (parameter type Error) + */ + @OnError + public void onError(Error error) + { + /* no impl */ + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidErrorExceptionSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidErrorExceptionSocket.java new file mode 100644 index 00000000000..da1448f6b7b --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidErrorExceptionSocket.java @@ -0,0 +1,37 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnError; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class InvalidErrorExceptionSocket extends TrackingSocket +{ + /** + * Invalid Error Method Declaration (parameter type Exception) + */ + @OnError + public void onError(Exception e) + { + /* no impl */ + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidErrorIntSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidErrorIntSocket.java new file mode 100644 index 00000000000..63df4a7e99d --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidErrorIntSocket.java @@ -0,0 +1,37 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnError; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class InvalidErrorIntSocket extends TrackingSocket +{ + /** + * Invalid Error Method Declaration (parameter type int) + */ + @OnError + public void onError(int errorCount) + { + /* no impl */ + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidOpenCloseReasonSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidOpenCloseReasonSocket.java new file mode 100644 index 00000000000..f2ef7bac1fd --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidOpenCloseReasonSocket.java @@ -0,0 +1,38 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.CloseReason; +import javax.websocket.OnOpen; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class InvalidOpenCloseReasonSocket extends TrackingSocket +{ + /** + * Invalid Open Method Declaration (parameter type CloseReason) + */ + @OnOpen + public void onOpen(CloseReason reason) + { + openLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidOpenIntSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidOpenIntSocket.java new file mode 100644 index 00000000000..9b9045a833e --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidOpenIntSocket.java @@ -0,0 +1,37 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnOpen; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class InvalidOpenIntSocket extends TrackingSocket +{ + /** + * Invalid Open Method Declaration (parameter type int) + */ + @OnOpen + public void onOpen(int value) + { + openLatch.countDown(); + } +} diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidOpenSessionIntSocket.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidOpenSessionIntSocket.java new file mode 100644 index 00000000000..8e127468ef1 --- /dev/null +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/InvalidOpenSessionIntSocket.java @@ -0,0 +1,38 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 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.server.samples; + +import javax.websocket.ClientEndpoint; +import javax.websocket.OnOpen; +import javax.websocket.Session; + +import org.eclipse.jetty.websocket.jsr356.server.TrackingSocket; + +@ClientEndpoint +public class InvalidOpenSessionIntSocket extends TrackingSocket +{ + /** + * Invalid Open Method Declaration (parameter of type int) + */ + @OnOpen + public void onOpen(Session session, int count) + { + openLatch.countDown(); + } +}