Parameter identification refactor + Decoder and PathParam integration

This commit is contained in:
Joakim Erdfelt 2013-03-22 13:17:56 -07:00
parent 0bab7b2c6d
commit a498107c42
59 changed files with 3001 additions and 325 deletions

View File

@ -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<JsrMetadata<?>>
{
private static final Logger LOG = Log.getLogger(AnnotatedEndpointScanner.class);
private final LinkedList<IJsrParamId> paramsOnOpen;
private final LinkedList<IJsrParamId> paramsOnClose;
private final LinkedList<IJsrParamId> paramsOnError;
private final LinkedList<IJsrParamId> 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<IJsrParamId> paramIds,
Class<? extends Annotation> 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<IJsrParamId> 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;
}
}

View File

@ -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<? extends Decoder> getMessageDecoder();
/**
* The type of message this method can handle
*
* @return the message type if &#064;{@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<? extends Decoder> decoderClass);
/**
* The type of message this method can handle
*
* @param type
* the type of message
*/
void setMessageType(MessageType type);
}

View File

@ -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.
* <p>
* 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;
}

View File

@ -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<T extends Annotation>
{
public final Class<?> pojo;
public Decoders decoders;
public Encoders encoders;
/**
* Callable for &#064;{@link OnOpen} annotation
*/
public ParameterizedMethod onOpen;
/**
* Callable for &#064;{@link OnClose} annotation
*/
public ParameterizedMethod onClose;
/**
* Callable for &#064;{@link OnError} annotation
*/
public ParameterizedMethod onError;
/**
* Callable for &#064;{@link OnMessage} annotation dealing with Text Message Format
*/
public ParameterizedMethod onText;
/**
* Callable for &#064;{@link OnMessage} annotation dealing with Binary Message Format
*/
public ParameterizedMethod onBinary;
/**
* Callable for &#064;{@link OnMessage} annotation dealing with Pong Message Format
*/
public ParameterizedMethod onPong;
protected JsrMetadata(Class<?> websocket)
{
this.pojo = websocket;
}
public void customizeParamsOnClose(LinkedList<IJsrParamId> params)
{
/* do nothing */
}
public void customizeParamsOnError(LinkedList<IJsrParamId> params)
{
/* do nothing */
}
public void customizeParamsOnMessage(LinkedList<IJsrParamId> params)
{
/* do nothing */
}
public void customizeParamsOnOpen(LinkedList<IJsrParamId> params)
{
/* do nothing */
}
public abstract T getAnnotation();
}

View File

@ -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 &#064;{@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<? extends Decoder> 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;
}
}

View File

@ -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 &#064;{@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;
}
}

View File

@ -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 &#064;{@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;
}
}

View File

@ -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 &#064;{@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;
}
}

View File

@ -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 <String> is supported with partial message boolean indicator.");
throw new InvalidSignatureException(err.toString());
}
}
}

View File

@ -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 &#064;{@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;
}
}

View File

@ -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;
}
}

View File

@ -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 &#064;{@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<? extends Decoder> 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;
}
}

View File

@ -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 &#064;{@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;
}
}

View File

@ -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;
}
}

View File

@ -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<Param>
{
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<Param> 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<? extends Decoder> 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<Param> iterator()
{
return methodParams.iterator();
}
@Override
public void setMessageDecoder(Class<? extends Decoder> decoderClass)
{
// TODO Auto-generated method stub
}
@Override
public void setMessageType(MessageType type)
{
this.messageType = type;
}
}

View File

@ -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<byte[]>
{
@Override
public byte[] decode(ByteBuffer bytes) throws DecodeException
{
return BufferUtil.toArray(bytes);
}
@Override
public boolean willDecode(ByteBuffer bytes)
{
return true;
}
}

View File

@ -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<DecoderRef>
{
private static class DecoderRef
public static class DecoderRef
{
Class<?> type;
Class<? extends Decoder> decoder;
@ -42,6 +44,16 @@ public class Decoders
this.type = type;
this.decoder = decoder;
}
public Class<? extends Decoder> getDecoder()
{
return decoder;
}
public Class<?> getType()
{
return type;
}
}
public static List<ParameterizedType> getDecoderInterfaces(Class<? extends Decoder> decoder)
@ -188,4 +200,10 @@ public class Decoders
throw new ConfigurationException("Unable to instantiate Decoder: " + decoderClass,e);
}
}
@Override
public Iterator<DecoderRef> iterator()
{
return decoders.iterator();
}
}

View File

@ -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<PongMessage>
{
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;
}
}

View File

@ -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 &#064;ClientEndpoint} annotated classes
*/
public class JsrAnnotatedClientImpl implements EventDriverImpl
{
private ConcurrentHashMap<Class<?>, 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);
}
}

View File

@ -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 &#064;WebSocketEndpoint} and {@link ClientEndpoint &#064;ClientEndpoint} annotated websockets
*/
public class JsrAnnotatedClientScanner extends AbstractMethodAnnotationScanner<JsrAnnotatedMetadata>
{
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<? extends Annotation> 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;
}
}

View File

@ -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<? extends Annotation> classAnnotation;
public Decoders decoders;
public Encoders encoders;
/**
* Callable for &#064;{@link OnOpen} annotation
*/
public CallableMethod onOpen;
/**
* Callable for &#064;{@link OnClose} annotation
*/
public CallableMethod onClose;
/**
* Callable for &#064;{@link OnError} annotation
*/
public CallableMethod onError;
/**
* Callable for &#064;{@link OnMessage} annotation dealing with Text Message Format
*/
public CallableMethod onText;
/**
* Callable for &#064;{@link OnMessage} annotation dealing with Binary Message Format
*/
public CallableMethod onBinary;
/**
* Callable for &#064;{@link OnMessage} annotation dealing with Pong Message Format
*/

View File

@ -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<ClientEndpoint>
{
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<IJsrParamId> params)
{
for (DecoderRef ref : decoders)
{
Class<? extends Decoder> 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;
}
}

View File

@ -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
}
}

View File

@ -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());

View File

@ -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<Case[]> data() throws Exception
{
List<Case[]> 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++)

View File

@ -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<Class<?>[]> data()
@ -81,7 +82,7 @@ public class JsrAnnotatedClientScanner_InvalidSignaturesTest
// The annotation class expected to be mentioned in the error message
private Class<? extends Annotation> expectedAnnoClass;
public JsrAnnotatedClientScanner_InvalidSignaturesTest(Class<?> pojo, Class<? extends Annotation> expectedAnnotation)
public ClientAnnotatedEndpointScanner_InvalidSignaturesTest(Class<?> pojo, Class<? extends Annotation> 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();

View File

@ -16,6 +16,11 @@
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-client-impl</artifactId>

View File

@ -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 &#064;{@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;
}
}

View File

@ -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();
}
}

View File

@ -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<ServerEndpoint>
{
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<IJsrParamId> params)
{
params.addFirst(JsrParamPath.INSTANCE);
}
@Override
public void customizeParamsOnError(LinkedList<IJsrParamId> params)
{
params.addFirst(JsrParamPath.INSTANCE);
}
@Override
public void customizeParamsOnOpen(LinkedList<IJsrParamId> params)
{
params.addFirst(JsrParamPath.INSTANCE);
}
@Override
public void customizeParamsOnMessage(LinkedList<IJsrParamId> params)
{
for (DecoderRef ref : decoders)
{
Class<? extends Decoder> 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);
}
}

View File

@ -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
}
}

View File

@ -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 &#64;{@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<DiscoveredAnnotation> 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<Value> 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<Value> 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<Value> values)
{
LOG.warn("@WebServlet annotation not supported for fields");
}
@Override
public String getAnnotationName()
{
return ANNOTATION_NAME;
}
}

View File

@ -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");
}
}

View File

@ -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<Case[]> 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<Case[]> data() throws Exception
{
List<Case[]> 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));
}
}
}

View File

@ -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<Class<?>[]> data()
{
List<Class<?>[]> 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<? extends Annotation> expectedAnnoClass;
public ServerAnnotatedEndpointScanner_InvalidSignaturesTest(Class<?> pojo, Class<? extends Annotation> 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()));
}
}
}

View File

@ -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<String> eventQueue = new BlockingArrayQueue<String>();
public BlockingQueue<Throwable> 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));
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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()");
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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 */
}
}

View File

@ -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 */
}
}

View File

@ -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 */
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}