Issue #207 - working @PathParam support

This commit is contained in:
Joakim Erdfelt 2017-02-23 15:38:57 -07:00
parent d8f06df8b2
commit 70d4850ed1
5 changed files with 64 additions and 33 deletions

View File

@ -370,7 +370,7 @@ public class AvailableDecoders implements Predicate<Class<?>>
} }
catch (NumberFormatException e) catch (NumberFormatException e)
{ {
throw new DecodeException(value, "Unable to decode as type " + type.getName()); throw new DecodeException(value, "Unable to decode as type " + type.getName(), e);
} }
} }

View File

@ -543,11 +543,12 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
{ {
Arg SESSION = new Arg(Session.class); Arg SESSION = new Arg(Session.class);
UnorderedSignature sigPong = new UnorderedSignature(createCallArgs(SESSION, new Arg(PongMessage.class).required())); UnorderedSignature sigPong = new UnorderedSignature(createCallArgs(SESSION, new Arg(PongMessage.class).required()));
if (sigPong.test(onMsg)) int argMapping[] = sigPong.getArgMapping(onMsg);
if (argMapping != null)
{ {
assertOnMessageSignature(onMsg); assertOnMessageSignature(onMsg);
final Object[] args = newCallArgs(sigPong.getCallArgs()); final Object[] args = newFunctionArgs(sigPong.getCallArgs(), onMsg, argMapping);
BiFunction<Object, Object[], Object> invoker = sigPong.newFunction(onMsg); BiFunction<Object, Object[], Object> invoker = sigPong.newFunction(onMsg);
// No decoder for PongMessage // No decoder for PongMessage
setOnPong((pong) -> setOnPong((pong) ->
@ -588,11 +589,12 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.BinaryStream.class)) for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.BinaryStream.class))
{ {
UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required()));
if (sig.test(onMsg)) int argMapping[] = sig.getArgMapping(onMsg);
if (argMapping != null)
{ {
assertOnMessageSignature(onMsg); assertOnMessageSignature(onMsg);
final Object[] args = newCallArgs(sig.getCallArgs()); final Object[] args = newFunctionArgs(sig.getCallArgs(), onMsg, argMapping);
BiFunction<Object, Object[], Object> invoker = sig.newFunction(onMsg); BiFunction<Object, Object[], Object> invoker = sig.newFunction(onMsg);
Decoder.BinaryStream decoderInstance = decoders.getInstanceOf(decoder); Decoder.BinaryStream decoderInstance = decoders.getInstanceOf(decoder);
DecodedInputStreamMessageSink streamSink = new DecodedInputStreamMessageSink( DecodedInputStreamMessageSink streamSink = new DecodedInputStreamMessageSink(
@ -627,11 +629,12 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.TextStream.class)) for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.TextStream.class))
{ {
UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required()));
if (sig.test(onMsg)) int argMapping[] = sig.getArgMapping(onMsg);
if (argMapping != null)
{ {
assertOnMessageSignature(onMsg); assertOnMessageSignature(onMsg);
final Object[] args = newCallArgs(sig.getCallArgs()); final Object[] args = newFunctionArgs(sig.getCallArgs(), onMsg, argMapping);
BiFunction<Object, Object[], Object> invoker = sig.newFunction(onMsg); BiFunction<Object, Object[], Object> invoker = sig.newFunction(onMsg);
Decoder.TextStream decoderInstance = decoders.getInstanceOf(decoder); Decoder.TextStream decoderInstance = decoders.getInstanceOf(decoder);
DecodedReaderMessageSink streamSink = new DecodedReaderMessageSink( DecodedReaderMessageSink streamSink = new DecodedReaderMessageSink(
@ -667,12 +670,13 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
Arg ARG_BYTE_BUFFER = new Arg(ByteBuffer.class).required(); Arg ARG_BYTE_BUFFER = new Arg(ByteBuffer.class).required();
Arg ARG_PARTIAL_BOOL = new Arg(boolean.class).required(); Arg ARG_PARTIAL_BOOL = new Arg(boolean.class).required();
UnorderedSignature sigPartialByteBuffer = new UnorderedSignature(createCallArgs(SESSION, ARG_BYTE_BUFFER, ARG_PARTIAL_BOOL)); UnorderedSignature sigPartialByteBuffer = new UnorderedSignature(createCallArgs(SESSION, ARG_BYTE_BUFFER, ARG_PARTIAL_BOOL));
if (sigPartialByteBuffer.test(onMsg)) int argMapping[] = sigPartialByteBuffer.getArgMapping(onMsg);
if (argMapping != null)
{ {
// Found partial binary array args // Found partial binary array args
assertOnMessageSignature(onMsg); assertOnMessageSignature(onMsg);
final Object[] args = newCallArgs(sigPartialByteBuffer.getCallArgs()); final Object[] args = newFunctionArgs(sigPartialByteBuffer.getCallArgs(), onMsg, argMapping);
BiFunction<Object, Object[], Object> invoker = sigPartialByteBuffer.newFunction(onMsg); BiFunction<Object, Object[], Object> invoker = sigPartialByteBuffer.newFunction(onMsg);
// No decoders for Partial messages per JSR-356 (PFD1 spec) // No decoders for Partial messages per JSR-356 (PFD1 spec)
setOnBinary(new PartialBinaryMessageSink((partial) -> setOnBinary(new PartialBinaryMessageSink((partial) ->
@ -703,12 +707,13 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
Arg ARG_BYTE_ARRAY = new Arg(byte[].class).required(); Arg ARG_BYTE_ARRAY = new Arg(byte[].class).required();
Arg ARG_PARTIAL_BOOL = new Arg(boolean.class).required(); Arg ARG_PARTIAL_BOOL = new Arg(boolean.class).required();
UnorderedSignature sigPartialBinaryArray = new UnorderedSignature(createCallArgs(SESSION, ARG_BYTE_ARRAY, ARG_PARTIAL_BOOL)); UnorderedSignature sigPartialBinaryArray = new UnorderedSignature(createCallArgs(SESSION, ARG_BYTE_ARRAY, ARG_PARTIAL_BOOL));
if (sigPartialBinaryArray.test(onMsg)) int argMapping[] = sigPartialBinaryArray.getArgMapping(onMsg);
if (argMapping != null)
{ {
// Found partial binary array args // Found partial binary array args
assertOnMessageSignature(onMsg); assertOnMessageSignature(onMsg);
final Object[] args = newCallArgs(sigPartialBinaryArray.getCallArgs()); final Object[] args = newFunctionArgs(sigPartialBinaryArray.getCallArgs(), onMsg, argMapping);
BiFunction<Object, Object[], Object> invoker = sigPartialBinaryArray.newFunction(onMsg); BiFunction<Object, Object[], Object> invoker = sigPartialBinaryArray.newFunction(onMsg);
// No decoders for Partial messages per JSR-356 (PFD1 spec) // No decoders for Partial messages per JSR-356 (PFD1 spec)
setOnBinary(new PartialBinaryMessageSink((partial) -> setOnBinary(new PartialBinaryMessageSink((partial) ->
@ -740,12 +745,14 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
Arg ARG_PARTIAL_BOOL = new Arg(boolean.class).required(); Arg ARG_PARTIAL_BOOL = new Arg(boolean.class).required();
Arg ARG_STRING = new Arg(String.class).required(); Arg ARG_STRING = new Arg(String.class).required();
UnorderedSignature sigPartialText = new UnorderedSignature(createCallArgs(SESSION, ARG_STRING, ARG_PARTIAL_BOOL)); UnorderedSignature sigPartialText = new UnorderedSignature(createCallArgs(SESSION, ARG_STRING, ARG_PARTIAL_BOOL));
if (sigPartialText.test(onMsg))
int argMapping[] = sigPartialText.getArgMapping(onMsg);
if (argMapping != null)
{ {
// Found partial text args // Found partial text args
assertOnMessageSignature(onMsg); assertOnMessageSignature(onMsg);
final Object[] args = newCallArgs(sigPartialText.getCallArgs()); final Object[] args = newFunctionArgs(sigPartialText.getCallArgs(), onMsg, argMapping);
BiFunction<Object, Object[], Object> invoker = sigPartialText.newFunction(onMsg); BiFunction<Object, Object[], Object> invoker = sigPartialText.newFunction(onMsg);
// No decoders for Partial messages per JSR-356 (PFD1 spec) // No decoders for Partial messages per JSR-356 (PFD1 spec)
setOnText(new PartialTextMessageSink((partial) -> setOnText(new PartialTextMessageSink((partial) ->
@ -776,11 +783,12 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.Binary.class)) for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.Binary.class))
{ {
UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required()));
if (sig.test(onMsg)) int argMapping[] = sig.getArgMapping(onMsg);
if (argMapping != null)
{ {
assertOnMessageSignature(onMsg); assertOnMessageSignature(onMsg);
final Object[] args = newCallArgs(sig.getCallArgs()); final Object[] args = newFunctionArgs(sig.getCallArgs(), onMsg, argMapping);
BiFunction<Object, Object[], Object> invoker = sig.newFunction(onMsg); BiFunction<Object, Object[], Object> invoker = sig.newFunction(onMsg);
Decoder.Binary decoderInstance = decoders.getInstanceOf(decoder); Decoder.Binary decoderInstance = decoders.getInstanceOf(decoder);
DecodedBinaryMessageSink binarySink = new DecodedBinaryMessageSink( DecodedBinaryMessageSink binarySink = new DecodedBinaryMessageSink(
@ -812,11 +820,12 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.Text.class)) for (AvailableDecoders.RegisteredDecoder decoder : decoders.supporting(Decoder.Text.class))
{ {
UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required())); UnorderedSignature sig = new UnorderedSignature(createCallArgs(SESSION, new Arg(decoder.objectType).required()));
if (sig.test(onMsg)) int argMapping[] = sig.getArgMapping(onMsg);
if (argMapping != null)
{ {
assertOnMessageSignature(onMsg); assertOnMessageSignature(onMsg);
final Object[] args = newCallArgs(sig.getCallArgs()); final Object[] args = newFunctionArgs(sig.getCallArgs(), onMsg, argMapping);
BiFunction<Object, Object[], Object> invoker = sig.newFunction(onMsg); BiFunction<Object, Object[], Object> invoker = sig.newFunction(onMsg);
Decoder.Text decoderInstance = decoders.getInstanceOf(decoder); Decoder.Text decoderInstance = decoders.getInstanceOf(decoder);
DecodedTextMessageSink textSink = new DecodedTextMessageSink( DecodedTextMessageSink textSink = new DecodedTextMessageSink(
@ -893,6 +902,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
} }
} }
@Deprecated
protected Object[] newCallArgs(Arg[] callArgs) throws DecodeException protected Object[] newCallArgs(Arg[] callArgs) throws DecodeException
{ {
int len = callArgs.length; int len = callArgs.length;
@ -905,6 +915,30 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
return args; return args;
} }
protected Object[] newFunctionArgs(Arg[] callArgs, Method destMethod, int argMapping[]) throws DecodeException
{
Object[] potentialArgs = new Object[callArgs.length];
if ((staticArgs == null) || (staticArgs.isEmpty()))
{
// No static args, then potentialArgs is empty too
return potentialArgs;
}
Class<?>[] paramTypes = destMethod.getParameterTypes();
int paramTypesLen = paramTypes.length;
for (int i = 0; i < paramTypesLen; i++)
{
Class destType = paramTypes[i];
Arg callArg = callArgs[argMapping[i]];
String staticRawValue = staticArgs.get(callArg.getTag());
potentialArgs[argMapping[i]] = AvailableDecoders.decodePrimitive(staticRawValue, destType);
}
return potentialArgs;
}
private Object getDecodedStaticValue(String name, Class<?> type) throws DecodeException private Object getDecodedStaticValue(String name, Class<?> type) throws DecodeException
{ {
String value = staticArgs.get(name); String value = staticArgs.get(name);

View File

@ -177,11 +177,14 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
AvailableDecoders availableDecoders = new AvailableDecoders(config); AvailableDecoders availableDecoders = new AvailableDecoders(config);
Map<String, String> pathParameters = new HashMap<>(); Map<String, String> pathParameters = new HashMap<>();
// if any pathspec has a URI Template with variables, we should include them (as empty String value) // if any pathspec has a URI Template with variables, we should include them (as String value 0)
// in the test for validity of the declared @OnMessage methods that use @PathParam annotation // in the test for validity of the declared @OnMessage methods that use @PathParam annotation
// We chose the default string "0" as that is the most reliably converted to a
// Java Primitive during this initial "is valid" test (the real URITemplate value
// is used when a real connection is established later)
for (String variable : new UriTemplatePathSpec(config.getPath()).getVariables()) for (String variable : new UriTemplatePathSpec(config.getPath()).getVariables())
{ {
pathParameters.put(variable, ""); pathParameters.put(variable, "0");
} }
endpointFunctions = newJsrEndpointFunction(endpoint, availableEncoders, availableDecoders, pathParameters, config); endpointFunctions = newJsrEndpointFunction(endpoint, availableEncoders, availableDecoders, pathParameters, config);

View File

@ -72,11 +72,17 @@ public class UnorderedSignature implements Signature, Predicate<Method>
} }
@Override @Override
@Deprecated
public boolean test(Method method) public boolean test(Method method)
{ {
return getArgMapping(method, false, callArgs) != null; return getArgMapping(method, false, callArgs) != null;
} }
public int[] getArgMapping(Method method)
{
return getArgMapping(method, false, callArgs);
}
public void appendDescription(StringBuilder str) public void appendDescription(StringBuilder str)
{ {
str.append('('); str.append('(');

12
pom.xml
View File

@ -1454,18 +1454,6 @@
<alpn.version>8.1.11.v20170118</alpn.version> <alpn.version>8.1.11.v20170118</alpn.version>
</properties> </properties>
</profile> </profile>
<profile>
<id>8u131</id>
<activation>
<property>
<name>java.version</name>
<value>1.8.0_131</value>
</property>
</activation>
<properties>
<alpn.version>8.1.11.v20170118</alpn.version>
</properties>
</profile>
</profiles> </profiles>
<issueManagement> <issueManagement>