Issue #207 - Support javax.websocket version 1.1

WIP
This commit is contained in:
Joakim Erdfelt 2016-04-22 16:52:56 -07:00
parent 5f6cf96fa5
commit 89f45830bc
21 changed files with 198 additions and 205 deletions

View File

@ -18,7 +18,6 @@
package org.eclipse.jetty.websocket.jsr356.messages;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.websocket.MessageHandler;
@ -42,17 +41,16 @@ public class TextPartialMessage implements MessageSink
}
@Override
public void appendFrame(ByteBuffer payload, boolean isLast) throws IOException
public void accept(ByteBuffer payload, Boolean fin)
{
String partialText = utf8Partial.toPartialString(payload);
// No decoders for Partial messages per JSR-356 (PFD1 spec)
partialHandler.onMessage(partialText,isLast);
}
partialHandler.onMessage(partialText, fin);
@Override
public void messageComplete()
{
utf8Partial.reset();
if (fin)
{
utf8Partial.reset();
}
}
}

View File

@ -24,25 +24,15 @@
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<onlyAnalyze>org.eclipse.jetty.websocket.*</onlyAnalyze>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>clirr-maven-plugin</artifactId>
<configuration>
<minSeverity>info</minSeverity>
<comparisonVersion>9.1.0.v20131115</comparisonVersion>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<onlyAnalyze>org.eclipse.jetty.websocket.*</onlyAnalyze>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -55,7 +55,7 @@ public abstract class ConnectPromise extends FuturePromise<Session> implements R
{
if (session != null)
{
// Notify websocket of failure to connect
// Notify websocket session of failure to connect
session.notifyError(cause);
}

View File

@ -65,23 +65,30 @@ public class ClientConnectTest
{
// Validate thrown cause
Throwable cause = e.getCause();
if(!errorClass.isInstance(cause))
if (!errorClass.isInstance(cause))
{
cause.printStackTrace(System.err);
Assert.assertThat("ExecutionException.cause",cause,instanceOf(errorClass));
cause.printStackTrace(System.err);
Assert.assertThat("ExecutionException.cause", cause, instanceOf(errorClass));
}
// Validate websocket captured cause
Assert.assertThat("Error Queue Length",wsocket.errorQueue.size(),greaterThanOrEqualTo(1));
Throwable capcause = wsocket.errorQueue.poll();
Assert.assertThat("Error Queue[0]",capcause,notNullValue());
Assert.assertThat("Error Queue[0]",capcause,instanceOf(errorClass));
if (wsocket.getSession() != null)
{
// Validate websocket captured cause
Assert.assertThat("Error Queue Length", wsocket.errorQueue.size(), greaterThanOrEqualTo(1));
Throwable capcause = wsocket.errorQueue.poll();
Assert.assertThat("Error Queue[0]", capcause, notNullValue());
Assert.assertThat("Error Queue[0]", capcause, instanceOf(errorClass));
// Validate that websocket didn't see an open event
wsocket.assertNotOpened();
// Validate that websocket didn't see an open event
wsocket.assertNotOpened();
// Return the captured cause
return (E)capcause;
// Return the captured cause
return (E) capcause;
}
else
{
return (E) cause;
}
}
@Before

View File

@ -38,18 +38,18 @@ import org.eclipse.jetty.websocket.common.util.ReflectUtils;
public class OnByteArrayFunction implements Function<byte[], Void>
{
private static final DynamicArgs.Builder ARGBUILDER;
private static final Arg SESSION = new Arg(1,Session.class);
private static final Arg BUFFER = new Arg(2,byte[].class);
private static final Arg OFFSET = new Arg(3,int.class);
private static final Arg LENGTH = new Arg(4,int.class);
private static final Arg ARG_SESSION = new Arg(1, Session.class);
private static final Arg ARG_BUFFER = new Arg(2, byte[].class);
private static final Arg ARG_OFFSET = new Arg(3, int.class);
private static final Arg ARG_LENGTH = new Arg(4, int.class);
static
{
ARGBUILDER = new DynamicArgs.Builder();
ARGBUILDER.addSignature(new ExactSignature(byte[].class));
ARGBUILDER.addSignature(new ExactSignature(byte[].class,int.class,int.class));
ARGBUILDER.addSignature(new ExactSignature(Session.class,byte[].class));
ARGBUILDER.addSignature(new ExactSignature(Session.class,byte[].class,int.class,int.class));
ARGBUILDER.addSignature(new ExactSignature(ARG_BUFFER));
ARGBUILDER.addSignature(new ExactSignature(ARG_BUFFER, ARG_OFFSET, ARG_LENGTH));
ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_BUFFER));
ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_BUFFER, ARG_OFFSET, ARG_LENGTH));
}
public static DynamicArgs.Builder getDynamicArgsBuilder()
@ -73,14 +73,14 @@ public class OnByteArrayFunction implements Function<byte[], Void>
this.endpoint = endpoint;
this.method = method;
ReflectUtils.assertIsAnnotated(method,OnWebSocketMessage.class);
ReflectUtils.assertIsAnnotated(method, OnWebSocketMessage.class);
ReflectUtils.assertIsPublicNonStatic(method);
ReflectUtils.assertIsReturn(method,Void.TYPE);
ReflectUtils.assertIsReturn(method, Void.TYPE);
this.callable = ARGBUILDER.build(method,SESSION,BUFFER,OFFSET,LENGTH);
this.callable = ARGBUILDER.build(method, ARG_SESSION, ARG_BUFFER, ARG_OFFSET, ARG_LENGTH);
if (this.callable == null)
{
throw InvalidSignatureException.build(method,OnWebSocketMessage.class,ARGBUILDER);
throw InvalidSignatureException.build(method, OnWebSocketMessage.class, ARGBUILDER);
}
}
@ -89,11 +89,11 @@ public class OnByteArrayFunction implements Function<byte[], Void>
{
try
{
this.callable.invoke(endpoint,bin,0,bin.length);
this.callable.invoke(endpoint, bin, 0, bin.length);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(),method),e);
throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e);
}
return null;
}

View File

@ -39,14 +39,14 @@ import org.eclipse.jetty.websocket.common.util.ReflectUtils;
public class OnByteBufferFunction implements Function<ByteBuffer, Void>
{
private static final DynamicArgs.Builder ARGBUILDER;
private static final Arg SESSION = new Arg(1,Session.class);
private static final Arg BUFFER = new Arg(2,ByteBuffer.class);
private static final Arg ARG_SESSION = new Arg(1, Session.class);
private static final Arg ARG_BUFFER = new Arg(2, ByteBuffer.class);
static
{
ARGBUILDER = new DynamicArgs.Builder();
ARGBUILDER.addSignature(new ExactSignature(ByteBuffer.class));
ARGBUILDER.addSignature(new ExactSignature(Session.class,ByteBuffer.class));
ARGBUILDER.addSignature(new ExactSignature(ARG_BUFFER));
ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_BUFFER));
}
public static DynamicArgs.Builder getDynamicArgsBuilder()
@ -70,14 +70,14 @@ public class OnByteBufferFunction implements Function<ByteBuffer, Void>
this.endpoint = endpoint;
this.method = method;
ReflectUtils.assertIsAnnotated(method,OnWebSocketMessage.class);
ReflectUtils.assertIsAnnotated(method, OnWebSocketMessage.class);
ReflectUtils.assertIsPublicNonStatic(method);
ReflectUtils.assertIsReturn(method,Void.TYPE);
ReflectUtils.assertIsReturn(method, Void.TYPE);
this.callable = ARGBUILDER.build(method,SESSION,BUFFER);
this.callable = ARGBUILDER.build(method, ARG_SESSION, ARG_BUFFER);
if (this.callable == null)
{
throw InvalidSignatureException.build(method,OnWebSocketMessage.class,ARGBUILDER);
throw InvalidSignatureException.build(method, OnWebSocketMessage.class, ARGBUILDER);
}
}
@ -86,11 +86,11 @@ public class OnByteBufferFunction implements Function<ByteBuffer, Void>
{
try
{
this.callable.invoke(endpoint,session,bin);
this.callable.invoke(endpoint, session, bin);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(),method),e);
throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e);
}
return null;
}

View File

@ -18,6 +18,10 @@
package org.eclipse.jetty.websocket.common.functions;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.Function;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
@ -29,27 +33,23 @@ import org.eclipse.jetty.websocket.common.util.DynamicArgs.Arg;
import org.eclipse.jetty.websocket.common.util.ExactSignature;
import org.eclipse.jetty.websocket.common.util.ReflectUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.Function;
/**
* Jetty {@link WebSocket} {@link OnWebSocketClose} method {@link Function}
*/
public class OnCloseFunction implements Function<CloseInfo, Void>
{
private static final DynamicArgs.Builder ARGBUILDER;
private static final Arg SESSION = new Arg(1,Session.class);
private static final Arg STATUS_CODE = new Arg(2,int.class);
private static final Arg REASON = new Arg(3,String.class);
private static final Arg ARG_SESSION = new Arg(1, Session.class);
private static final Arg ARG_STATUS_CODE = new Arg(2, int.class);
private static final Arg ARG_REASON = new Arg(3, String.class);
static
{
ARGBUILDER = new DynamicArgs.Builder();
ARGBUILDER.addSignature(new ExactSignature());
ARGBUILDER.addSignature(new ExactSignature(Session.class));
ARGBUILDER.addSignature(new ExactSignature(int.class,String.class));
ARGBUILDER.addSignature(new ExactSignature(Session.class,int.class,String.class));
ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION));
ARGBUILDER.addSignature(new ExactSignature(ARG_STATUS_CODE, ARG_REASON));
ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_STATUS_CODE, ARG_REASON));
}
private final Session session;
@ -67,10 +67,10 @@ public class OnCloseFunction implements Function<CloseInfo, Void>
ReflectUtils.assertIsPublicNonStatic(method);
ReflectUtils.assertIsReturn(method, Void.TYPE);
this.callable = ARGBUILDER.build(method, SESSION, STATUS_CODE, REASON);
this.callable = ARGBUILDER.build(method, ARG_SESSION, ARG_STATUS_CODE, ARG_REASON);
if (this.callable == null)
{
throw InvalidSignatureException.build(method,OnWebSocketClose.class,ARGBUILDER);
throw InvalidSignatureException.build(method, OnWebSocketClose.class, ARGBUILDER);
}
}
@ -79,11 +79,11 @@ public class OnCloseFunction implements Function<CloseInfo, Void>
{
try
{
this.callable.invoke(endpoint,session,closeinfo.getStatusCode(),closeinfo.getReason());
this.callable.invoke(endpoint, session, closeinfo.getStatusCode(), closeinfo.getReason());
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
throw new WebSocketException("Unable to call close method " + ReflectUtils.toString(endpoint.getClass(),method),e);
throw new WebSocketException("Unable to call close method " + ReflectUtils.toString(endpoint.getClass(), method), e);
}
return null;
}

View File

@ -38,14 +38,14 @@ import org.eclipse.jetty.websocket.common.util.ReflectUtils;
public class OnErrorFunction implements Function<Throwable, Void>
{
private static final DynamicArgs.Builder ARGBUILDER;
private static final Arg SESSION = new Arg(1, Session.class);
private static final Arg CAUSE = new Arg(2, Throwable.class);
private static final Arg ARG_SESSION = new Arg(1, Session.class);
private static final Arg ARG_CAUSE = new Arg(2, Throwable.class);
static
{
ARGBUILDER = new DynamicArgs.Builder();
ARGBUILDER.addSignature(new ExactSignature(Throwable.class));
ARGBUILDER.addSignature(new ExactSignature(Session.class,Throwable.class));
ARGBUILDER.addSignature(new ExactSignature(ARG_CAUSE));
ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_CAUSE));
}
private final Session session;
@ -59,14 +59,14 @@ public class OnErrorFunction implements Function<Throwable, Void>
this.endpoint = endpoint;
this.method = method;
ReflectUtils.assertIsAnnotated(method,OnWebSocketError.class);
ReflectUtils.assertIsAnnotated(method, OnWebSocketError.class);
ReflectUtils.assertIsPublicNonStatic(method);
ReflectUtils.assertIsReturn(method,Void.TYPE);
ReflectUtils.assertIsReturn(method, Void.TYPE);
this.callable = ARGBUILDER.build(method,SESSION,CAUSE);
this.callable = ARGBUILDER.build(method, ARG_SESSION, ARG_CAUSE);
if (this.callable == null)
{
throw InvalidSignatureException.build(method,OnWebSocketError.class,ARGBUILDER);
throw InvalidSignatureException.build(method, OnWebSocketError.class, ARGBUILDER);
}
}
@ -75,11 +75,11 @@ public class OnErrorFunction implements Function<Throwable, Void>
{
try
{
this.callable.invoke(endpoint,session,cause);
this.callable.invoke(endpoint, session, cause);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
throw new WebSocketException("Unable to call error method " + ReflectUtils.toString(endpoint.getClass(),method),e);
throw new WebSocketException("Unable to call error method " + ReflectUtils.toString(endpoint.getClass(), method), e);
}
return null;
}

View File

@ -40,14 +40,14 @@ import org.eclipse.jetty.websocket.common.util.ReflectUtils;
public class OnFrameFunction implements Function<Frame, Void>
{
private static final DynamicArgs.Builder ARGBUILDER;
private static final Arg SESSION = new Arg(1,Session.class);
private static final Arg FRAME = new Arg(2,Frame.class);
private static final Arg ARG_SESSION = new Arg(1, Session.class);
private static final Arg ARG_FRAME = new Arg(2, Frame.class);
static
{
ARGBUILDER = new DynamicArgs.Builder();
ARGBUILDER.addSignature(new ExactSignature(Frame.class));
ARGBUILDER.addSignature(new ExactSignature(Session.class,Frame.class));
ARGBUILDER.addSignature(new ExactSignature(ARG_FRAME));
ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_FRAME));
}
private final Session session;
@ -61,14 +61,14 @@ public class OnFrameFunction implements Function<Frame, Void>
this.endpoint = endpoint;
this.method = method;
ReflectUtils.assertIsAnnotated(method,OnWebSocketFrame.class);
ReflectUtils.assertIsAnnotated(method, OnWebSocketFrame.class);
ReflectUtils.assertIsPublicNonStatic(method);
ReflectUtils.assertIsReturn(method,Void.TYPE);
ReflectUtils.assertIsReturn(method, Void.TYPE);
this.callable = ARGBUILDER.build(method,SESSION,FRAME);
this.callable = ARGBUILDER.build(method, ARG_SESSION, ARG_FRAME);
if (this.callable == null)
{
throw InvalidSignatureException.build(method,OnWebSocketFrame.class,ARGBUILDER);
throw InvalidSignatureException.build(method, OnWebSocketFrame.class, ARGBUILDER);
}
}
@ -78,11 +78,11 @@ public class OnFrameFunction implements Function<Frame, Void>
WebSocketFrame copy = WebSocketFrame.copy(frame);
try
{
this.callable.invoke(endpoint,session,copy);
this.callable.invoke(endpoint, session, copy);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
throw new WebSocketException("Unable to call frame method " + ReflectUtils.toString(endpoint.getClass(),method),e);
throw new WebSocketException("Unable to call frame method " + ReflectUtils.toString(endpoint.getClass(), method), e);
}
return null;
}

View File

@ -40,14 +40,14 @@ import org.eclipse.jetty.websocket.common.util.ReflectUtils;
public class OnInputStreamFunction implements Function<InputStream, Void>
{
private static final DynamicArgs.Builder ARGBUILDER;
private static final Arg SESSION = new Arg(1,Session.class);
private static final Arg STREAM = new Arg(2, InputStream.class);
private static final Arg ARG_SESSION = new Arg(1, Session.class);
private static final Arg ARG_STREAM = new Arg(2, InputStream.class);
static
{
ARGBUILDER = new DynamicArgs.Builder();
ARGBUILDER.addSignature(new ExactSignature(InputStream.class));
ARGBUILDER.addSignature(new ExactSignature(Session.class,InputStream.class));
ARGBUILDER.addSignature(new ExactSignature(ARG_STREAM));
ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_STREAM));
}
public static DynamicArgs.Builder getDynamicArgsBuilder()
@ -71,14 +71,14 @@ public class OnInputStreamFunction implements Function<InputStream, Void>
this.endpoint = endpoint;
this.method = method;
ReflectUtils.assertIsAnnotated(method,OnWebSocketMessage.class);
ReflectUtils.assertIsAnnotated(method, OnWebSocketMessage.class);
ReflectUtils.assertIsPublicNonStatic(method);
ReflectUtils.assertIsReturn(method,Void.TYPE);
ReflectUtils.assertIsReturn(method, Void.TYPE);
this.callable = ARGBUILDER.build(method,SESSION,STREAM);
this.callable = ARGBUILDER.build(method, ARG_SESSION, ARG_STREAM);
if (this.callable == null)
{
throw InvalidSignatureException.build(method,OnWebSocketMessage.class,ARGBUILDER);
throw InvalidSignatureException.build(method, OnWebSocketMessage.class, ARGBUILDER);
}
}
@ -87,11 +87,11 @@ public class OnInputStreamFunction implements Function<InputStream, Void>
{
try
{
this.callable.invoke(endpoint,session,stream);
this.callable.invoke(endpoint, session, stream);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(),method),e);
throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e);
}
return null;
}

View File

@ -38,13 +38,13 @@ import org.eclipse.jetty.websocket.common.util.ReflectUtils;
public class OnOpenFunction implements Function<Session, Void>
{
private static final DynamicArgs.Builder ARGBUILDER;
private static final Arg SESSION = new Arg(1,Session.class);
private static final Arg ARG_SESSION = new Arg(1, Session.class);
static
{
ARGBUILDER = new DynamicArgs.Builder();
ARGBUILDER.addSignature(new ExactSignature());
ARGBUILDER.addSignature(new ExactSignature(Session.class));
ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION));
}
private final Object endpoint;
@ -56,14 +56,14 @@ public class OnOpenFunction implements Function<Session, Void>
this.endpoint = endpoint;
this.method = method;
ReflectUtils.assertIsAnnotated(method,OnWebSocketConnect.class);
ReflectUtils.assertIsAnnotated(method, OnWebSocketConnect.class);
ReflectUtils.assertIsPublicNonStatic(method);
ReflectUtils.assertIsReturn(method,Void.TYPE);
ReflectUtils.assertIsReturn(method, Void.TYPE);
this.callable = ARGBUILDER.build(method,SESSION);
this.callable = ARGBUILDER.build(method, ARG_SESSION);
if (this.callable == null)
{
throw InvalidSignatureException.build(method,OnWebSocketConnect.class,ARGBUILDER);
throw InvalidSignatureException.build(method, OnWebSocketConnect.class, ARGBUILDER);
}
}
@ -72,11 +72,11 @@ public class OnOpenFunction implements Function<Session, Void>
{
try
{
this.callable.invoke(endpoint,session);
this.callable.invoke(endpoint, session);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
throw new WebSocketException("Unable to call method " + ReflectUtils.toString(endpoint.getClass(),method),e);
throw new WebSocketException("Unable to call method " + ReflectUtils.toString(endpoint.getClass(), method), e);
}
return null;
}

View File

@ -39,14 +39,14 @@ import org.eclipse.jetty.websocket.common.util.ReflectUtils;
public class OnReaderFunction implements Function<Reader, Void>
{
private static final DynamicArgs.Builder ARGBUILDER;
private static final Arg SESSION = new Arg(1,Session.class);
private static final Arg STREAM = new Arg(2,Reader.class);
private static final Arg ARG_SESSION = new Arg(1, Session.class);
private static final Arg ARG_STREAM = new Arg(2, Reader.class);
static
{
ARGBUILDER = new DynamicArgs.Builder();
ARGBUILDER.addSignature(new ExactSignature(Reader.class));
ARGBUILDER.addSignature(new ExactSignature(Session.class,Reader.class));
ARGBUILDER.addSignature(new ExactSignature(ARG_STREAM));
ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_STREAM));
}
public static DynamicArgs.Builder getDynamicArgsBuilder()
@ -70,14 +70,14 @@ public class OnReaderFunction implements Function<Reader, Void>
this.endpoint = endpoint;
this.method = method;
ReflectUtils.assertIsAnnotated(method,OnWebSocketMessage.class);
ReflectUtils.assertIsAnnotated(method, OnWebSocketMessage.class);
ReflectUtils.assertIsPublicNonStatic(method);
ReflectUtils.assertIsReturn(method,Void.TYPE);
ReflectUtils.assertIsReturn(method, Void.TYPE);
this.callable = ARGBUILDER.build(method,SESSION,STREAM);
this.callable = ARGBUILDER.build(method, ARG_SESSION, ARG_STREAM);
if (this.callable == null)
{
throw InvalidSignatureException.build(method,OnWebSocketMessage.class,ARGBUILDER);
throw InvalidSignatureException.build(method, OnWebSocketMessage.class, ARGBUILDER);
}
}
@ -86,11 +86,11 @@ public class OnReaderFunction implements Function<Reader, Void>
{
try
{
this.callable.invoke(endpoint,session,stream);
this.callable.invoke(endpoint, session, stream);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(),method),e);
throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e);
}
return null;
}

View File

@ -33,19 +33,19 @@ import org.eclipse.jetty.websocket.common.util.ExactSignature;
import org.eclipse.jetty.websocket.common.util.ReflectUtils;
/**
* Jetty {@link WebSocket} {@link OnWebSocketMessage} method {@link Function} for TEXT/{@link String} types
* Jetty {@link WebSocket} {@link OnWebSocketMessage} method {@link Function} for ARG_TEXT/{@link String} types
*/
public class OnTextFunction implements Function<String, Void>
{
private static final DynamicArgs.Builder ARGBUILDER;
private static final Arg SESSION = new Arg(1,Session.class);
private static final Arg TEXT = new Arg(2,String.class);
private static final Arg ARG_SESSION = new Arg(1, Session.class);
private static final Arg ARG_TEXT = new Arg(2, String.class);
static
{
ARGBUILDER = new DynamicArgs.Builder();
ARGBUILDER.addSignature(new ExactSignature(String.class));
ARGBUILDER.addSignature(new ExactSignature(Session.class,String.class));
ARGBUILDER.addSignature(new ExactSignature(ARG_TEXT));
ARGBUILDER.addSignature(new ExactSignature(ARG_SESSION, ARG_TEXT));
}
public static DynamicArgs.Builder getDynamicArgsBuilder()
@ -69,14 +69,14 @@ public class OnTextFunction implements Function<String, Void>
this.endpoint = endpoint;
this.method = method;
ReflectUtils.assertIsAnnotated(method,OnWebSocketMessage.class);
ReflectUtils.assertIsAnnotated(method, OnWebSocketMessage.class);
ReflectUtils.assertIsPublicNonStatic(method);
ReflectUtils.assertIsReturn(method,Void.TYPE);
ReflectUtils.assertIsReturn(method, Void.TYPE);
this.callable = ARGBUILDER.build(method,SESSION,TEXT);
this.callable = ARGBUILDER.build(method, ARG_SESSION, ARG_TEXT);
if (this.callable == null)
{
throw InvalidSignatureException.build(method,OnWebSocketMessage.class,ARGBUILDER);
throw InvalidSignatureException.build(method, OnWebSocketMessage.class, ARGBUILDER);
}
}
@ -85,11 +85,11 @@ public class OnTextFunction implements Function<String, Void>
{
try
{
this.callable.invoke(endpoint,session,text);
this.callable.invoke(endpoint, session, text);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(),method),e);
throw new WebSocketException("Unable to call text message method " + ReflectUtils.toString(endpoint.getClass(), method), e);
}
return null;
}

View File

@ -18,8 +18,6 @@
package org.eclipse.jetty.websocket.common.util;
import org.eclipse.jetty.util.annotation.Name;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@ -101,7 +99,7 @@ public class DynamicArgs
@Override
public String toString()
{
return String.format("%s[%d%s]",type.getSimpleName(),index,tag == null ? "" : "/" + tag);
return String.format("%s[%d%s]",type.getName(),index,tag == null ? "" : "/" + tag);
}
public <T extends Annotation> T getAnnotation(Class<T> annoClass)

View File

@ -22,7 +22,6 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import org.eclipse.jetty.websocket.common.util.DynamicArgs.Arg;
import org.eclipse.jetty.websocket.common.util.DynamicArgs.Signature;
@ -41,17 +40,6 @@ public class ExactSignature implements Signature, BiPredicate<Method,Class<?>[]>
this.params = params;
}
public ExactSignature(Class<?>... parameters)
{
int len = parameters.length;
this.params = new Arg[len];
for(int i=0; i<len; i++)
{
this.params[i] = new Arg(i, parameters[i]);
}
}
@Override
public BiPredicate<Method,Class<?>[]> getPredicate()
{

View File

@ -20,12 +20,9 @@ package org.eclipse.jetty.websocket.common.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import org.eclipse.jetty.websocket.common.util.DynamicArgs.Arg;
import org.eclipse.jetty.websocket.common.util.DynamicArgs.Signature;
@ -34,7 +31,7 @@ public class UnorderedSignature implements Signature, BiPredicate<Method, Class<
{
private final Arg[] params;
public UnorderedSignature(Arg ... args)
public UnorderedSignature(Arg... args)
{
this.params = args;
}
@ -113,43 +110,55 @@ public class UnorderedSignature implements Signature, BiPredicate<Method, Class<
@Override
public BiFunction<Object, Object[], Object> getInvoker(Method method, Arg... callArgs)
{
int callArgsLen = callArgs.length;
// Figure out mapping of calling args to method args
Class<?> paramTypes[] = method.getParameterTypes();
int paramTypesLength = paramTypes.length;
// Method argument array pointing to index in calling array
int argMapping[] = new int[paramTypesLength];
int callArgsLen = callArgs.length;
int argMappingLength = argMapping.length;
// ServiceLoader for argument identification plugins
List<ArgIdentifier> argIdentifiers = DynamicArgs.lookupArgIdentifiers();
for (int mi = 0; mi < paramTypesLength; mi++)
DynamicArgs.Arg methodArgs[] = new DynamicArgs.Arg[paramTypesLength];
for (int pi = 0; pi < paramTypesLength; pi++)
{
DynamicArgs.Arg methodArg = new DynamicArgs.Arg(method, mi, paramTypes[mi]);
methodArgs[pi] = new DynamicArgs.Arg(method, pi, paramTypes[pi]);
// Supplement method argument identification from plugins
for (ArgIdentifier argId : argIdentifiers)
methodArg = argId.apply(methodArg);
methodArgs[pi] = argId.apply(methodArgs[pi]);
}
// Iterate through mappings, looking for a callArg that fits it
for (int ai = 0; ai < argMappingLength; ai++)
{
int ref = -1;
// Find reference to argument in callArgs
for (int ci = 0; ci < callArgsLen; ci++)
{
if (methodArg.tag != null && methodArg.tag.equals(callArgs[ci].tag))
if (methodArgs[ai].tag != null && methodArgs[ai].tag.equals(callArgs[ci].tag))
{
ref = ci;
break;
}
else if (methodArg.index == callArgs[ci].index)
else if (methodArgs[ai].index == callArgs[ci].index)
{
ref = ci;
break;
}
}
if (ref < 0)
{
StringBuilder err = new StringBuilder();
err.append("Unable to map type [");
err.append(params[mi]);
err.append(methodArgs[ai].type);
err.append("] in method ");
ReflectUtils.append(err,method);
ReflectUtils.append(err, method);
err.append(" to calling args: (");
boolean delim = false;
for (Arg arg : callArgs)
@ -163,7 +172,8 @@ public class UnorderedSignature implements Signature, BiPredicate<Method, Class<
throw new DynamicArgsException(err.toString());
}
argMapping[mi] = ref;
argMapping[ai] = ref;
}
// Return function capable of calling method
@ -175,13 +185,13 @@ public class UnorderedSignature implements Signature, BiPredicate<Method, Class<
}
try
{
return method.invoke(obj,args);
return method.invoke(obj, args);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
StringBuilder err = new StringBuilder();
err.append("Unable to call: ");
ReflectUtils.append(err,obj.getClass(),method);
ReflectUtils.append(err, obj.getClass(), method);
err.append(" [with ");
boolean delim = false;
for (Object arg : args)
@ -199,7 +209,7 @@ public class UnorderedSignature implements Signature, BiPredicate<Method, Class<
delim = true;
}
err.append("]");
throw new DynamicArgsException(err.toString(),e);
throw new DynamicArgsException(err.toString(), e);
}
};
}

View File

@ -155,22 +155,21 @@ public class MessageInputStreamTest
{
final AtomicBoolean hadError = new AtomicBoolean(false);
new Thread(new Runnable()
{
@Override
public void run()
new Thread(() -> {
try
{
try
{
// wait for a little bit before sending input closed
TimeUnit.MILLISECONDS.sleep(400);
// TODO: stream.messageComplete();
}
catch (InterruptedException e)
{
hadError.set(true);
e.printStackTrace(System.err);
}
// wait for a little bit before sending input closed
TimeUnit.MILLISECONDS.sleep(400);
stream.close();
}
catch (InterruptedException e)
{
hadError.set(true);
e.printStackTrace(System.err);
}
catch (IOException e)
{
e.printStackTrace(System.err);
}
}).start();
@ -180,7 +179,7 @@ public class MessageInputStreamTest
// Test it
Assert.assertThat("Error when appending",hadError.get(),is(false));
Assert.assertThat("Initial byte",b,is(-1));
Assert.assertThat("Initial byte (Should be EOF)",b,is(-1));
}
}

View File

@ -58,12 +58,13 @@ public class MessageWriterTest
private WebSocketPolicy policy;
private TrackingSocket remoteSocket;
private WebSocketSession session;
private WebSocketSession remoteSession;
@After
public void closeSession() throws Exception
{
session.close();
session.stop();
remoteSession.close();
}
@Before
@ -80,8 +81,9 @@ public class MessageWriterTest
remoteSocket = new TrackingSocket("remote");
URI remoteURI = new URI("ws://localhost/remote");
LocalWebSocketConnection remoteConnection = new LocalWebSocketConnection(bufferPool);
WebSocketSession remoteSession = new WebSocketSession(containerScope,remoteURI,remoteSocket,remoteConnection);
remoteSession = new WebSocketSession(containerScope,remoteURI,remoteSocket,remoteConnection);
OutgoingFrames socketPipe = FramePipes.to(remoteSession);
remoteSession.open();
// Local Session
TrackingSocket localSocket = new TrackingSocket("local");

View File

@ -39,12 +39,12 @@ public class ExactSignatureTest
public String sigStr(String str)
{
return String.format("sigStr<%s>",str);
return String.format("sigStr<%s>", str);
}
public String sigByteArray(byte[] buf, int offset, int len)
{
return String.format("sigByteArray<%s,%d,%d>",buf == null ? "<null>" : ("[" + buf.length + "]"),offset,len);
return String.format("sigByteArray<%s,%d,%d>", buf == null ? "<null>" : ("[" + buf.length + "]"), offset, len);
}
}
@ -60,12 +60,12 @@ public class ExactSignatureTest
throw new AssertionError("Unable to find method: " + name);
}
private static final Arg ARG_STR = new Arg(1,String.class);
private static final Arg ARG_BOOL = new Arg(2,Boolean.class);
private static final Arg ARG_FILE = new Arg(3,File.class);
private static final Arg ARG_BYTEARRAY = new Arg(4,byte[].class);
private static final Arg ARG_OFFSET = new Arg(5,int.class);
private static final Arg ARG_LEN = new Arg(6,int.class);
private static final Arg ARG_STR = new Arg(1, String.class);
private static final Arg ARG_BOOL = new Arg(2, Boolean.class);
private static final Arg ARG_FILE = new Arg(3, File.class);
private static final Arg ARG_BYTEARRAY = new Arg(4, byte[].class);
private static final Arg ARG_OFFSET = new Arg(5, int.class);
private static final Arg ARG_LEN = new Arg(6, int.class);
@Test
public void testEmptySignature() throws Exception
@ -75,11 +75,11 @@ public class ExactSignatureTest
SampleSignatures ssigs = new SampleSignatures();
Method m = findMethodByName(ssigs, "sigEmpty");
DynamicArgs dargs = dab.build(m,ARG_STR,ARG_BOOL,ARG_FILE);
DynamicArgs dargs = dab.build(m, ARG_STR, ARG_BOOL, ARG_FILE);
assertThat("DynamicArgs", dargs, notNullValue());
// Test with potential args
String result = (String)dargs.invoke(ssigs,"Hello", Boolean.TRUE, new File("bar"));
String result = (String) dargs.invoke(ssigs, "Hello", Boolean.TRUE, new File("bar"));
assertThat("result", result, is("sigEmpty<>"));
}
@ -91,11 +91,11 @@ public class ExactSignatureTest
SampleSignatures ssigs = new SampleSignatures();
Method m = findMethodByName(ssigs, "sigStr");
DynamicArgs dargs = dab.build(m,ARG_STR,ARG_BOOL,ARG_FILE);
DynamicArgs dargs = dab.build(m, ARG_STR, ARG_BOOL, ARG_FILE);
assertThat("DynamicArgs", dargs, notNullValue());
// Test with potential args
String result = (String)dargs.invoke(ssigs,"Hello", Boolean.TRUE, new File("bar"));
String result = (String) dargs.invoke(ssigs, "Hello", Boolean.TRUE, new File("bar"));
assertThat("result", result, is("sigStr<Hello>"));
}
@ -103,22 +103,22 @@ public class ExactSignatureTest
public void testByteArraySignature() throws Exception
{
DynamicArgs.Builder dab = new DynamicArgs.Builder();
dab.addSignature(new ExactSignature(ARG_BYTEARRAY,ARG_OFFSET,ARG_LEN));
dab.addSignature(new ExactSignature(ARG_BYTEARRAY, ARG_OFFSET, ARG_LEN));
SampleSignatures ssigs = new SampleSignatures();
Method m = findMethodByName(ssigs, "sigByteArray");
DynamicArgs dargs = dab.build(m,ARG_BYTEARRAY,ARG_OFFSET,ARG_LEN);
DynamicArgs dargs = dab.build(m, ARG_BYTEARRAY, ARG_OFFSET, ARG_LEN);
assertThat("DynamicArgs", dargs, notNullValue());
// Test with potential args
byte buf[] = new byte[222];
int offset = 3;
int len = 44;
String result = (String)dargs.invoke(ssigs,buf,offset,len);
String result = (String) dargs.invoke(ssigs, buf, offset, len);
assertThat("result", result, is("sigByteArray<[222],3,44>"));
// Test with empty potential args
result = (String)dargs.invoke(ssigs,null,123,456);
result = (String) dargs.invoke(ssigs, null, 123, 456);
assertThat("result", result, is("sigByteArray<<null>,123,456>"));
}
}

View File

@ -174,11 +174,11 @@ public class UnorderedSignatureTest
byte buf[] = new byte[222];
int offset = 3;
int len = 44;
String result = (String)dargs.invoke(m,ssigs,buf,offset,len);
String result = (String)dargs.invoke(ssigs,buf,offset,len);
assertThat("result", result, is("sigByteArray<[222],3,44>"));
// Test with empty potential args
result = (String)dargs.invoke(m,ssigs,null,123,456);
result = (String)dargs.invoke(ssigs,null,123,456);
assertThat("result", result, is("sigByteArray<<null>,123,456>"));
}
}

View File

@ -5,3 +5,4 @@ org.eclipse.jetty.LEVEL=WARN
# org.eclipse.jetty.websocket.protocol.LEVEL=DEBUG
# org.eclipse.jetty.websocket.io.payload.LEVEL=DEBUG
# org.eclipse.jetty.websocket.common.extensions.LEVEL=DEBUG
# org.eclipse.jetty.websocket.common.message.LEVEL=DEBUG