Issue #207 - Cleaning up Args vs Signature classes
This commit is contained in:
parent
daf79bf4a9
commit
f6b4b7b3e3
|
@ -58,7 +58,6 @@ import org.eclipse.jetty.websocket.common.message.MessageSink;
|
|||
import org.eclipse.jetty.websocket.common.message.PartialBinaryMessageSink;
|
||||
import org.eclipse.jetty.websocket.common.message.PartialTextMessageSink;
|
||||
import org.eclipse.jetty.websocket.common.reflect.Arg;
|
||||
import org.eclipse.jetty.websocket.common.reflect.DynamicArgs;
|
||||
import org.eclipse.jetty.websocket.common.reflect.UnorderedSignature;
|
||||
import org.eclipse.jetty.websocket.common.util.ReflectUtils;
|
||||
import org.eclipse.jetty.websocket.jsr356.JsrPongMessage;
|
||||
|
@ -78,12 +77,12 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
{
|
||||
private static final Logger LOG = Log.getLogger(JsrEndpointFunctions.class);
|
||||
|
||||
protected static class MessageHandlerPongFunction implements Function<ByteBuffer, Void>
|
||||
private static class MessageHandlerPongFunction implements Function<ByteBuffer, Void>
|
||||
{
|
||||
public final MessageHandler messageHandler;
|
||||
final MessageHandler messageHandler;
|
||||
public final Function<ByteBuffer, Void> function;
|
||||
|
||||
public MessageHandlerPongFunction(MessageHandler messageHandler, Function<ByteBuffer, Void> function)
|
||||
MessageHandlerPongFunction(MessageHandler messageHandler, Function<ByteBuffer, Void> function)
|
||||
{
|
||||
this.messageHandler = messageHandler;
|
||||
this.function = function;
|
||||
|
@ -96,12 +95,12 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
}
|
||||
}
|
||||
|
||||
protected static class MessageHandlerSink implements MessageSink
|
||||
private static class MessageHandlerSink implements MessageSink
|
||||
{
|
||||
public final MessageHandler messageHandler;
|
||||
public final MessageSink delegateSink;
|
||||
final MessageHandler messageHandler;
|
||||
final MessageSink delegateSink;
|
||||
|
||||
public MessageHandlerSink(MessageHandler messageHandler, MessageSink messageSink)
|
||||
MessageHandlerSink(MessageHandler messageHandler, MessageSink messageSink)
|
||||
{
|
||||
this.messageHandler = messageHandler;
|
||||
this.delegateSink = messageSink;
|
||||
|
@ -140,6 +139,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public AvailableDecoders getAvailableDecoders()
|
||||
{
|
||||
return decoders;
|
||||
|
@ -196,6 +196,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
{
|
||||
PartialTextMessageSink sink = new PartialTextMessageSink((partial) ->
|
||||
{
|
||||
//noinspection unchecked
|
||||
handler.onMessage((T) partial.getPayload(), partial.isFin());
|
||||
return null;
|
||||
});
|
||||
|
@ -207,6 +208,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
{
|
||||
PartialBinaryMessageSink sink = new PartialBinaryMessageSink((partial) ->
|
||||
{
|
||||
//noinspection unchecked
|
||||
handler.onMessage((T) partial.getPayload(), partial.isFin());
|
||||
return null;
|
||||
});
|
||||
|
@ -254,6 +256,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
{
|
||||
Function<ByteBuffer, Void> pongFunction = (payload) ->
|
||||
{
|
||||
//noinspection unchecked
|
||||
handler.onMessage((T) new JsrPongMessage(payload));
|
||||
return null;
|
||||
};
|
||||
|
@ -271,6 +274,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
policy, this, decoderInstance,
|
||||
(msg) ->
|
||||
{
|
||||
//noinspection unchecked
|
||||
handler.onMessage((T) msg);
|
||||
return null;
|
||||
}
|
||||
|
@ -286,6 +290,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
policy, this, decoderInstance,
|
||||
(msg) ->
|
||||
{
|
||||
//noinspection unchecked
|
||||
handler.onMessage((T) msg);
|
||||
return null;
|
||||
}
|
||||
|
@ -301,6 +306,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
this, decoderInstance,
|
||||
(msg) ->
|
||||
{
|
||||
//noinspection unchecked
|
||||
handler.onMessage((T) msg);
|
||||
return null;
|
||||
}
|
||||
|
@ -316,6 +322,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
this, decoderInstance,
|
||||
(msg) ->
|
||||
{
|
||||
//noinspection unchecked
|
||||
handler.onMessage((T) msg);
|
||||
return null;
|
||||
}
|
||||
|
@ -425,7 +432,8 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
protected void discoverJsrAnnotatedEndpointFunctions(Object endpoint) throws DecodeException
|
||||
{
|
||||
Class<?> endpointClass = endpoint.getClass();
|
||||
Method method = null;
|
||||
Method method;
|
||||
Arg SESSION = new Arg(Session.class);
|
||||
|
||||
// OnOpen [0..1]
|
||||
method = ReflectUtils.findAnnotatedMethod(endpointClass, OnOpen.class);
|
||||
|
@ -433,24 +441,29 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
{
|
||||
ReflectUtils.assertIsPublicNonStatic(method);
|
||||
ReflectUtils.assertIsReturn(method, Void.TYPE);
|
||||
|
||||
Arg ENDPOINT_CONFIG = new Arg(EndpointConfig.class);
|
||||
|
||||
// Analyze @OnOpen method declaration techniques
|
||||
DynamicArgs.Builder builder = createDynamicArgs(
|
||||
new Arg(Session.class),
|
||||
new Arg(EndpointConfig.class));
|
||||
UnorderedSignature sigOpen = new UnorderedSignature(
|
||||
createCallArgs(SESSION, ENDPOINT_CONFIG));
|
||||
|
||||
DynamicArgs.Signature sig = builder.getMatchingSignature(method);
|
||||
assertSignatureValid(sig, OnOpen.class, method);
|
||||
|
||||
final Object[] args = newCallArgs(sig.getCallArgs());
|
||||
DynamicArgs invoker = builder.build(method, sig);
|
||||
setOnOpen((jsrSession) ->
|
||||
int argMapping[] = sigOpen.getArgMapping(method, true);
|
||||
if(argMapping != null)
|
||||
{
|
||||
args[0] = jsrSession;
|
||||
args[1] = endpointConfig;
|
||||
invoker.invoke(endpoint, args);
|
||||
return null;
|
||||
}, method);
|
||||
assertSignatureValid(sigOpen, OnOpen.class, method);
|
||||
|
||||
final Object[] args = newFunctionArgs(sigOpen.getCallArgs(), method, argMapping);
|
||||
BiFunction<Object, Object[], Object> invoker = sigOpen.newFunction(method);
|
||||
|
||||
setOnOpen((jsrSession) ->
|
||||
{
|
||||
args[0] = jsrSession;
|
||||
args[1] = endpointConfig;
|
||||
invoker.apply(endpoint, args);
|
||||
return null;
|
||||
}, method);
|
||||
}
|
||||
}
|
||||
|
||||
// OnClose [0..1]
|
||||
|
@ -460,26 +473,31 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
ReflectUtils.assertIsPublicNonStatic(method);
|
||||
ReflectUtils.assertIsReturn(method, Void.TYPE);
|
||||
|
||||
Arg CLOSE_REASON = new Arg(CloseReason.class);
|
||||
|
||||
// Analyze @OnClose method declaration techniques
|
||||
DynamicArgs.Builder builder = createDynamicArgs(
|
||||
new Arg(Session.class),
|
||||
new Arg(CloseReason.class));
|
||||
UnorderedSignature sigClose = new UnorderedSignature(
|
||||
createCallArgs(SESSION, CLOSE_REASON));
|
||||
|
||||
DynamicArgs.Signature sig = builder.getMatchingSignature(method);
|
||||
assertSignatureValid(sig, OnClose.class, method);
|
||||
|
||||
final Object[] args = newCallArgs(sig.getCallArgs());
|
||||
DynamicArgs invoker = builder.build(method, sig);
|
||||
setOnClose((closeInfo) ->
|
||||
int argMapping[] = sigClose.getArgMapping(method, true);
|
||||
if(argMapping != null)
|
||||
{
|
||||
// Convert Jetty CloseInfo to JSR CloseReason
|
||||
CloseReason.CloseCode closeCode = CloseReason.CloseCodes.getCloseCode(closeInfo.getStatusCode());
|
||||
CloseReason closeReason = new CloseReason(closeCode, closeInfo.getReason());
|
||||
args[0] = getSession();
|
||||
args[1] = closeReason;
|
||||
invoker.invoke(endpoint, args);
|
||||
return null;
|
||||
}, method);
|
||||
assertSignatureValid(sigClose, OnClose.class, method);
|
||||
|
||||
final Object[] args = newFunctionArgs(sigClose.getCallArgs(), method, argMapping);
|
||||
BiFunction<Object, Object[], Object> invoker = sigClose.newFunction(method);
|
||||
|
||||
setOnClose((closeInfo) ->
|
||||
{
|
||||
// Convert Jetty CloseInfo to JSR CloseReason
|
||||
CloseReason.CloseCode closeCode = CloseReason.CloseCodes.getCloseCode(closeInfo.getStatusCode());
|
||||
CloseReason closeReason = new CloseReason(closeCode, closeInfo.getReason());
|
||||
args[0] = getSession();
|
||||
args[1] = closeReason;
|
||||
invoker.apply(endpoint, args);
|
||||
return null;
|
||||
}, method);
|
||||
}
|
||||
}
|
||||
|
||||
// OnError [0..1]
|
||||
|
@ -489,47 +507,50 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
ReflectUtils.assertIsPublicNonStatic(method);
|
||||
ReflectUtils.assertIsReturn(method, Void.TYPE);
|
||||
|
||||
Arg CAUSE = new Arg(Throwable.class);
|
||||
|
||||
// Analyze @OnError method declaration techniques
|
||||
DynamicArgs.Builder builder = createDynamicArgs(
|
||||
new Arg(Session.class),
|
||||
new Arg(Throwable.class));
|
||||
UnorderedSignature sigError = new UnorderedSignature(
|
||||
createCallArgs(SESSION, CAUSE));
|
||||
|
||||
DynamicArgs.Signature sig = builder.getMatchingSignature(method);
|
||||
assertSignatureValid(sig, OnError.class, method);
|
||||
|
||||
final Object[] args = newCallArgs(sig.getCallArgs());
|
||||
DynamicArgs invoker = builder.build(method, sig);
|
||||
setOnError((cause) ->
|
||||
int argMapping[] = sigError.getArgMapping(method, true);
|
||||
if(argMapping != null)
|
||||
{
|
||||
args[0] = getSession();
|
||||
args[1] = cause;
|
||||
invoker.invoke(endpoint, args);
|
||||
return null;
|
||||
}, method);
|
||||
assertSignatureValid(sigError, OnError.class, method);
|
||||
|
||||
final Object[] args = newFunctionArgs(sigError.getCallArgs(), method, argMapping);
|
||||
BiFunction<Object, Object[], Object> invoker = sigError.newFunction(method);
|
||||
setOnError((cause) ->
|
||||
{
|
||||
args[0] = getSession();
|
||||
args[1] = cause;
|
||||
invoker.apply(endpoint, args);
|
||||
return null;
|
||||
}, method);
|
||||
}
|
||||
}
|
||||
|
||||
// OnMessage [0..3] (TEXT / BINARY / PONG)
|
||||
Method onMessages[] = ReflectUtils.findAnnotatedMethods(endpointClass, OnMessage.class);
|
||||
if (onMessages != null && onMessages.length > 0)
|
||||
{
|
||||
onmsgloop:
|
||||
for (Method onMsg : onMessages)
|
||||
{
|
||||
// Whole TEXT / Binary Message
|
||||
if (discoverOnMessageWholeText(onMsg)) continue onmsgloop;
|
||||
if (discoverOnMessageWholeBinary(onMsg)) continue onmsgloop;
|
||||
if (discoverOnMessageWholeText(onMsg)) continue;
|
||||
if (discoverOnMessageWholeBinary(onMsg)) continue;
|
||||
|
||||
// Partial TEXT / BINARY
|
||||
if (discoverOnMessagePartialText(onMsg)) continue onmsgloop;
|
||||
if (discoverOnMessagePartialBinaryArray(onMsg)) continue onmsgloop;
|
||||
if (discoverOnMessagePartialBinaryBuffer(onMsg)) continue onmsgloop;
|
||||
if (discoverOnMessagePartialText(onMsg)) continue;
|
||||
if (discoverOnMessagePartialBinaryArray(onMsg)) continue;
|
||||
if (discoverOnMessagePartialBinaryBuffer(onMsg)) continue;
|
||||
|
||||
// Streaming TEXT / BINARY
|
||||
if (discoverOnMessageTextStream(onMsg)) continue onmsgloop;
|
||||
if (discoverOnMessageBinaryStream(onMsg)) continue onmsgloop;
|
||||
if (discoverOnMessageTextStream(onMsg)) continue;
|
||||
if (discoverOnMessageBinaryStream(onMsg)) continue;
|
||||
|
||||
// PONG
|
||||
if (discoverOnMessagePong(onMsg)) continue onmsgloop;
|
||||
if (discoverOnMessagePong(onMsg)) continue;
|
||||
|
||||
// If we reached this point, then we have a @OnMessage annotated method
|
||||
// that doesn't match any known signature above.
|
||||
|
@ -851,7 +872,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
return false;
|
||||
}
|
||||
|
||||
private void assertSignatureValid(DynamicArgs.Signature sig, Class<? extends Annotation> annotationClass, Method method)
|
||||
private void assertSignatureValid(UnorderedSignature sig, Class<? extends Annotation> annotationClass, Method method)
|
||||
{
|
||||
if (sig != null)
|
||||
return;
|
||||
|
@ -902,20 +923,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected Object[] newCallArgs(Arg[] callArgs) throws DecodeException
|
||||
{
|
||||
int len = callArgs.length;
|
||||
Object[] args = new Object[callArgs.length];
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
String staticRawValue = staticArgs.get(callArgs[i].getTag());
|
||||
args[i] = AvailableDecoders.decodePrimitive(staticRawValue, callArgs[i].getType());
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
protected Object[] newFunctionArgs(Arg[] callArgs, Method destMethod, int argMapping[]) throws DecodeException
|
||||
private Object[] newFunctionArgs(Arg[] callArgs, Method destMethod, int argMapping[]) throws DecodeException
|
||||
{
|
||||
Object[] potentialArgs = new Object[callArgs.length];
|
||||
|
||||
|
@ -939,21 +947,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
|||
return potentialArgs;
|
||||
}
|
||||
|
||||
private Object getDecodedStaticValue(String name, Class<?> type) throws DecodeException
|
||||
{
|
||||
String value = staticArgs.get(name);
|
||||
return AvailableDecoders.decodePrimitive(value, type);
|
||||
}
|
||||
|
||||
private DynamicArgs.Builder createDynamicArgs(Arg... args)
|
||||
{
|
||||
DynamicArgs.Builder argBuilder = new DynamicArgs.Builder();
|
||||
Arg[] callArgs = createCallArgs(args);
|
||||
argBuilder.addSignature(callArgs);
|
||||
return argBuilder;
|
||||
}
|
||||
|
||||
protected Arg[] createCallArgs(Arg... args)
|
||||
private Arg[] createCallArgs(Arg... args)
|
||||
{
|
||||
int argCount = args.length;
|
||||
if (this.staticArgs != null)
|
||||
|
|
|
@ -24,6 +24,11 @@ import org.eclipse.jetty.websocket.api.WebSocketException;
|
|||
|
||||
public class FunctionCallException extends WebSocketException
|
||||
{
|
||||
public FunctionCallException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public FunctionCallException(String message, Throwable cause)
|
||||
{
|
||||
super(message, cause);
|
||||
|
|
|
@ -64,7 +64,6 @@ import org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection;
|
|||
import org.eclipse.jetty.websocket.common.io.IOState;
|
||||
import org.eclipse.jetty.websocket.common.io.IOState.ConnectionStateListener;
|
||||
import org.eclipse.jetty.websocket.common.message.MessageSink;
|
||||
import org.eclipse.jetty.websocket.common.reflect.DynamicArgsException;
|
||||
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
|
||||
import org.eclipse.jetty.websocket.common.scopes.WebSocketSessionScope;
|
||||
|
||||
|
@ -288,12 +287,8 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Rem
|
|||
{
|
||||
if (t instanceof FunctionCallException)
|
||||
{
|
||||
return ((FunctionCallException) t).getInvokedCause();
|
||||
}
|
||||
else if (t instanceof DynamicArgsException)
|
||||
{
|
||||
Throwable cause = ((DynamicArgsException) t).getInvokedCause();
|
||||
if (cause != null)
|
||||
Throwable cause = ((FunctionCallException) t).getInvokedCause();
|
||||
if(cause != null)
|
||||
return cause;
|
||||
}
|
||||
|
||||
|
|
|
@ -241,7 +241,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
|
||||
this.batchMode = websocket.batchMode();
|
||||
|
||||
Method onmethod = null;
|
||||
Method onmethod;
|
||||
|
||||
// OnWebSocketConnect [0..1]
|
||||
onmethod = ReflectUtils.findAnnotatedMethod(endpointClass, OnWebSocketConnect.class);
|
||||
|
@ -524,7 +524,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
return onPongFunction;
|
||||
}
|
||||
|
||||
public void setOnOpen(Function<T, Void> function, Object origin)
|
||||
protected void setOnOpen(Function<T, Void> function, Object origin)
|
||||
{
|
||||
assertNotSet(this.onOpenFunction, "Open Handler", origin);
|
||||
this.onOpenFunction = function;
|
||||
|
@ -534,7 +534,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
}
|
||||
}
|
||||
|
||||
public void setOnClose(Function<CloseInfo, Void> function, Object origin)
|
||||
protected void setOnClose(Function<CloseInfo, Void> function, Object origin)
|
||||
{
|
||||
assertNotSet(this.onCloseFunction, "Close Handler", origin);
|
||||
this.onCloseFunction = function;
|
||||
|
@ -544,7 +544,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
}
|
||||
}
|
||||
|
||||
public void setOnError(Function<Throwable, Void> function, Object origin)
|
||||
protected void setOnError(Function<Throwable, Void> function, Object origin)
|
||||
{
|
||||
assertNotSet(this.onErrorFunction, "Error Handler", origin);
|
||||
this.onErrorFunction = function;
|
||||
|
@ -554,7 +554,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
}
|
||||
}
|
||||
|
||||
public void setOnText(MessageSink messageSink, Object origin)
|
||||
protected void setOnText(MessageSink messageSink, Object origin)
|
||||
{
|
||||
assertNotSet(this.onTextSink, "TEXT Handler", origin);
|
||||
this.onTextSink = messageSink;
|
||||
|
@ -564,7 +564,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
}
|
||||
}
|
||||
|
||||
public void setOnBinary(MessageSink messageSink, Object origin)
|
||||
protected void setOnBinary(MessageSink messageSink, Object origin)
|
||||
{
|
||||
assertNotSet(this.onBinarySink, "BINARY Handler", origin);
|
||||
this.onBinarySink = messageSink;
|
||||
|
@ -574,7 +574,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
}
|
||||
}
|
||||
|
||||
public void setOnFrame(Function<Frame, Void> function, Object origin)
|
||||
protected void setOnFrame(Function<Frame, Void> function, Object origin)
|
||||
{
|
||||
assertNotSet(this.onFrameFunction, "Frame Handler", origin);
|
||||
this.onFrameFunction = function;
|
||||
|
@ -584,7 +584,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
}
|
||||
}
|
||||
|
||||
public void setOnPing(Function<ByteBuffer, Void> function, Object origin)
|
||||
protected void setOnPing(Function<ByteBuffer, Void> function, Object origin)
|
||||
{
|
||||
assertNotSet(this.onPingFunction, "Ping Handler", origin);
|
||||
this.onPingFunction = function;
|
||||
|
@ -594,7 +594,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
}
|
||||
}
|
||||
|
||||
public void setOnPong(Function<ByteBuffer, Void> function, Object origin)
|
||||
protected void setOnPong(Function<ByteBuffer, Void> function, Object origin)
|
||||
{
|
||||
assertNotSet(this.onPongFunction, "Pong Handler", origin);
|
||||
this.onPongFunction = function;
|
||||
|
@ -644,7 +644,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
return obj.toString();
|
||||
}
|
||||
|
||||
protected void assertNotSet(Object val, String role, Object origin)
|
||||
private void assertNotSet(Object val, String role, Object origin)
|
||||
{
|
||||
if (val == null)
|
||||
return;
|
||||
|
@ -759,7 +759,7 @@ public class CommonEndpointFunctions<T extends Session> extends AbstractLifeCycl
|
|||
onPongFunction.apply(payload);
|
||||
}
|
||||
|
||||
protected void assertIsStarted()
|
||||
private void assertIsStarted()
|
||||
{
|
||||
if (!isStarted())
|
||||
throw new IllegalStateException(this.getClass().getName() + " not started");
|
||||
|
|
|
@ -18,31 +18,28 @@
|
|||
|
||||
package org.eclipse.jetty.websocket.common.reflect;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class DynamicArgsException extends RuntimeException
|
||||
public class ArgIdentifiers
|
||||
{
|
||||
public DynamicArgsException(String message, Throwable cause)
|
||||
private static List<ArgIdentifier> argIdentifiers;
|
||||
|
||||
public static List<ArgIdentifier> get()
|
||||
{
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public DynamicArgsException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
public Throwable getInvokedCause()
|
||||
{
|
||||
Throwable cause = getCause();
|
||||
if (cause == null)
|
||||
return null;
|
||||
|
||||
if (cause instanceof InvocationTargetException)
|
||||
if (argIdentifiers == null)
|
||||
{
|
||||
return cause.getCause();
|
||||
ServiceLoader<ArgIdentifier> loader = ServiceLoader.load(ArgIdentifier.class);
|
||||
List<ArgIdentifier> identifiers = new ArrayList<>();
|
||||
for (ArgIdentifier argId : loader)
|
||||
{
|
||||
identifiers.add(argId);
|
||||
}
|
||||
argIdentifiers = Collections.unmodifiableList(identifiers);
|
||||
}
|
||||
return cause;
|
||||
|
||||
return argIdentifiers;
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.common.reflect;
|
||||
|
||||
/**
|
||||
* A set of potential arguments, only one of which is allowed
|
||||
*/
|
||||
public class ArgSwitch extends Arg
|
||||
{
|
||||
public ArgSwitch(Class<?> type)
|
||||
{
|
||||
super(type);
|
||||
}
|
||||
}
|
|
@ -1,185 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.common.reflect;
|
||||
|
||||
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.Predicate;
|
||||
|
||||
/**
|
||||
* Provide argument utilities for working with methods that
|
||||
* have a dynamic assortment of arguments.
|
||||
* <ol>
|
||||
* <li>Can identify a set of parameters as matching the Builder</li>
|
||||
* <li>Can create a DynamicArgs for the matched signature</li>
|
||||
* <li>Can create an argument array for the provided potential arguments,
|
||||
* suitable to be used with {@link Method#invoke(Object, Object...)}</li>
|
||||
* </ol>
|
||||
*/
|
||||
public class DynamicArgs
|
||||
{
|
||||
public interface Signature
|
||||
{
|
||||
/**
|
||||
* Predicate to test if signature matches
|
||||
*
|
||||
* @return the predicate to test if signature matches
|
||||
*/
|
||||
Predicate<Method> getPredicate();
|
||||
|
||||
/**
|
||||
* Get Call Args
|
||||
*
|
||||
* @return the Call Args
|
||||
*/
|
||||
Arg[] getCallArgs();
|
||||
|
||||
/**
|
||||
* BiFunction to use to invoke method
|
||||
* against give object, with provided (potential) arguments,
|
||||
* returning appropriate result from invocation.
|
||||
*
|
||||
* @param method the method to base BiFunction off of.
|
||||
* @param callArgs the description of arguments passed into each {@link DynamicArgs#invoke(Object, Object...)}
|
||||
* call in the future. Used to map the incoming arguments to the method arguments.
|
||||
* @return the return result of the invoked method
|
||||
*/
|
||||
BiFunction<Object, Object[], Object> getInvoker(Method method, Arg... callArgs);
|
||||
|
||||
void appendDescription(StringBuilder str);
|
||||
}
|
||||
|
||||
public static class Builder implements Predicate<Method>
|
||||
{
|
||||
private List<Signature> signatures = new ArrayList<>();
|
||||
|
||||
public DynamicArgs build(Method method, Arg... callArgs)
|
||||
{
|
||||
Signature signature = getMatchingSignature(method);
|
||||
if (signature == null)
|
||||
return null;
|
||||
return build(method, signature);
|
||||
}
|
||||
|
||||
public DynamicArgs build(Method method, Signature signature)
|
||||
{
|
||||
return new DynamicArgs(signature.getInvoker(method, signature.getCallArgs()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(Method method)
|
||||
{
|
||||
return hasMatchingSignature(method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to identify a possible method signature match.
|
||||
*
|
||||
* @param method the method to test
|
||||
* @return true if it is a match
|
||||
*/
|
||||
public boolean hasMatchingSignature(Method method)
|
||||
{
|
||||
return getMatchingSignature(method) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link Signature} that matches the method
|
||||
*
|
||||
* @param method the method to inspect
|
||||
* @return the Signature, or null if no signature match
|
||||
*/
|
||||
public Signature getMatchingSignature(Method method)
|
||||
{
|
||||
// FIXME: add match cache (key = method, value = signature)
|
||||
|
||||
for (Signature sig : signatures)
|
||||
{
|
||||
if (sig.getPredicate().test(method))
|
||||
{
|
||||
return sig;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Builder addSignature(Arg... args)
|
||||
{
|
||||
signatures.add(new UnorderedSignature(args));
|
||||
return this;
|
||||
}
|
||||
|
||||
public void appendDescription(StringBuilder err)
|
||||
{
|
||||
for (Signature sig : signatures)
|
||||
{
|
||||
err.append(System.lineSeparator());
|
||||
sig.appendDescription(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static List<ArgIdentifier> argIdentifiers;
|
||||
|
||||
public static List<ArgIdentifier> lookupArgIdentifiers()
|
||||
{
|
||||
if (argIdentifiers == null)
|
||||
{
|
||||
ServiceLoader<ArgIdentifier> loader = ServiceLoader.load(ArgIdentifier.class);
|
||||
argIdentifiers = new ArrayList<>();
|
||||
for (ArgIdentifier argId : loader)
|
||||
{
|
||||
argIdentifiers.add(argId);
|
||||
}
|
||||
}
|
||||
|
||||
return argIdentifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* BiFunction invoker
|
||||
* <ol>
|
||||
* <li>First Arg</li>
|
||||
* <li>Second Arg</li>
|
||||
* <li>Result Type</li>
|
||||
* </ol>
|
||||
*/
|
||||
private final BiFunction<Object, Object[], Object> invoker;
|
||||
|
||||
public DynamicArgs(BiFunction<Object, Object[], Object> invoker)
|
||||
{
|
||||
this.invoker = invoker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoke the signature / method with the provided potential args.
|
||||
*
|
||||
* @param o the object to call method on
|
||||
* @param potentialArgs the potential args in the same order as the Call Args
|
||||
* @return the response object from the invoke
|
||||
*/
|
||||
public Object invoke(Object o, Object... potentialArgs)
|
||||
{
|
||||
return invoker.apply(o, potentialArgs);
|
||||
}
|
||||
}
|
|
@ -22,14 +22,14 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.common.reflect.DynamicArgs.Signature;
|
||||
import org.eclipse.jetty.websocket.common.FunctionCallException;
|
||||
import org.eclipse.jetty.websocket.common.InvalidSignatureException;
|
||||
import org.eclipse.jetty.websocket.common.util.ReflectUtils;
|
||||
|
||||
public class UnorderedSignature implements Signature, Predicate<Method>
|
||||
public class UnorderedSignature
|
||||
{
|
||||
private class SelectedArg extends Arg
|
||||
{
|
||||
|
@ -59,30 +59,31 @@ public class UnorderedSignature implements Signature, Predicate<Method>
|
|||
this.callArgs = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Arg[] getCallArgs()
|
||||
{
|
||||
return this.callArgs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<Method> getPredicate()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public boolean test(Method method)
|
||||
{
|
||||
return getArgMapping(method, false, callArgs) != null;
|
||||
}
|
||||
|
||||
public int[] getArgMapping(Method method)
|
||||
{
|
||||
return getArgMapping(method, false, callArgs);
|
||||
}
|
||||
|
||||
public int[] getArgMapping(Method method, boolean throwOnFailure)
|
||||
{
|
||||
return getArgMapping(method, throwOnFailure, callArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the provided method is a match for this UnorderedSignature declaration
|
||||
* @param method the method to test
|
||||
* @return true if a match, false if not a match
|
||||
*/
|
||||
public boolean test(Method method)
|
||||
{
|
||||
return getArgMapping(method, false, callArgs) != null;
|
||||
}
|
||||
|
||||
public void appendDescription(StringBuilder str)
|
||||
{
|
||||
str.append('(');
|
||||
|
@ -116,7 +117,7 @@ public class UnorderedSignature implements Signature, Predicate<Method>
|
|||
* </p>
|
||||
*
|
||||
* @param method the method that we want to eventually call
|
||||
* @param throwOnFailure true to toss a {@link DynamicArgsException} if there is a problem
|
||||
* @param throwOnFailure true to toss a {@link org.eclipse.jetty.websocket.common.FunctionCallException} if there is a problem
|
||||
* attempting to identify the mapping. false to debug log the issue.
|
||||
* @param callArgs the calling args for this signature
|
||||
*/
|
||||
|
@ -133,7 +134,7 @@ public class UnorderedSignature implements Signature, Predicate<Method>
|
|||
int argMappingLength = argMapping.length;
|
||||
|
||||
// ServiceLoader for argument identification plugins
|
||||
List<ArgIdentifier> argIdentifiers = DynamicArgs.lookupArgIdentifiers();
|
||||
List<ArgIdentifier> argIdentifiers = ArgIdentifiers.get();
|
||||
Arg methodArgs[] = new Arg[paramTypesLength];
|
||||
for (int pi = 0; pi < paramTypesLength; pi++)
|
||||
{
|
||||
|
@ -187,7 +188,7 @@ public class UnorderedSignature implements Signature, Predicate<Method>
|
|||
|
||||
if (throwOnFailure)
|
||||
{
|
||||
throw new DynamicArgsException(err.toString());
|
||||
throw new InvalidSignatureException(err.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -214,7 +215,7 @@ public class UnorderedSignature implements Signature, Predicate<Method>
|
|||
ReflectUtils.append(err, method);
|
||||
|
||||
if (throwOnFailure)
|
||||
throw new DynamicArgsException(err.toString());
|
||||
throw new FunctionCallException(err.toString());
|
||||
else
|
||||
{
|
||||
LOG.debug("{}", err.toString());
|
||||
|
@ -226,7 +227,6 @@ public class UnorderedSignature implements Signature, Predicate<Method>
|
|||
return argMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<Object, Object[], Object> getInvoker(Method method, Arg... callArgs)
|
||||
{
|
||||
int argMapping[] = getArgMapping(method, true, callArgs);
|
||||
|
@ -297,7 +297,7 @@ public class UnorderedSignature implements Signature, Predicate<Method>
|
|||
delim = true;
|
||||
}
|
||||
err.append("]");
|
||||
throw new DynamicArgsException(err.toString(), e);
|
||||
throw new FunctionCallException(err.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,335 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2016 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.common.reflect;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DynamicArgsTest
|
||||
{
|
||||
public static class A
|
||||
{
|
||||
private final String id;
|
||||
|
||||
public A(String id)
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return String.format("A:%s",id);
|
||||
}
|
||||
}
|
||||
|
||||
public static class B
|
||||
{
|
||||
private final int val;
|
||||
|
||||
public B(int val)
|
||||
{
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return String.format("B:%d",val);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static class SampleSignatures
|
||||
{
|
||||
public String sigEmpty()
|
||||
{
|
||||
return "sigEmpty<>";
|
||||
}
|
||||
|
||||
public String sigStr(String str)
|
||||
{
|
||||
return String.format("sigStr<%s>", q(str));
|
||||
}
|
||||
|
||||
public String sigStrFile(String str, File foo)
|
||||
{
|
||||
return String.format("sigStrFile<%s,%s>", q(str), q(foo));
|
||||
}
|
||||
|
||||
public String sigFileStr(File foo, String str)
|
||||
{
|
||||
return String.format("sigFileStr<%s,%s>", q(foo), q(str));
|
||||
}
|
||||
|
||||
public String sigFileStrFin(File foo, String str, @Name("fin") boolean fin)
|
||||
{
|
||||
return String.format("sigFileStrFin<%s,%s,%b>", q(foo), q(str), fin);
|
||||
}
|
||||
|
||||
public String sigByteArray(byte[] buf, @Name("offset") int offset, @Name("length") int len)
|
||||
{
|
||||
return String.format("sigByteArray<%s,%d,%d>", buf == null ? "<null>" : ("[" + buf.length + "]"), offset, len);
|
||||
}
|
||||
|
||||
public String sigObjectArgs(A a, B b)
|
||||
{
|
||||
return String.format("sigObjectArgs<%s,%s>", q(a), q(b));
|
||||
}
|
||||
|
||||
public String sigObjectA(A a)
|
||||
{
|
||||
return String.format("sigObjectA<%s>", q(a));
|
||||
}
|
||||
|
||||
public String sigObjectB(B b)
|
||||
{
|
||||
return String.format("sigObjectB<%s>", q(b));
|
||||
}
|
||||
|
||||
private String q(Object obj)
|
||||
{
|
||||
if (obj == null)
|
||||
return "<null>";
|
||||
else
|
||||
return obj.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static Method findMethodByName(Object obj, String name)
|
||||
{
|
||||
for (Method method : obj.getClass().getMethods())
|
||||
{
|
||||
if (method.getName().equals(name))
|
||||
{
|
||||
return method;
|
||||
}
|
||||
}
|
||||
throw new AssertionError("Unable to find method: " + name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with method that has empty signature,
|
||||
* and desired callable that also has an empty signature
|
||||
*
|
||||
* @throws Exception on error
|
||||
*/
|
||||
@Test
|
||||
public void testEmptySignature() throws Exception
|
||||
{
|
||||
DynamicArgs.Builder dab = new DynamicArgs.Builder();
|
||||
dab.addSignature(); // intentionally empty
|
||||
|
||||
SampleSignatures samples = new SampleSignatures();
|
||||
Method m = findMethodByName(samples, "sigEmpty");
|
||||
DynamicArgs dynamicArgs = dab.build(m);
|
||||
assertThat("DynamicArgs", dynamicArgs, notNullValue());
|
||||
|
||||
// Test with empty potential args
|
||||
String result = (String) dynamicArgs.invoke(samples);
|
||||
assertThat("result", result, is("sigEmpty<>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with method that has empty signature,
|
||||
* and desired callable that has a String (optional) signature
|
||||
*
|
||||
* @throws Exception on error
|
||||
*/
|
||||
@Test
|
||||
public void testEmptySignature_StringCallable() throws Exception
|
||||
{
|
||||
final Arg ARG_STR = new Arg(String.class);
|
||||
|
||||
DynamicArgs.Builder dab = new DynamicArgs.Builder();
|
||||
dab.addSignature(ARG_STR);
|
||||
|
||||
SampleSignatures samples = new SampleSignatures();
|
||||
Method m = findMethodByName(samples, "sigEmpty");
|
||||
DynamicArgs dynamicArgs = dab.build(m);
|
||||
assertThat("DynamicArgs", dynamicArgs, notNullValue());
|
||||
|
||||
// Test with empty potential args
|
||||
String result = (String) dynamicArgs.invoke(samples, "Hello");
|
||||
assertThat("result", result, is("sigEmpty<>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test with method that has String signature, and
|
||||
* a desired callable that also has String signature.
|
||||
*
|
||||
* @throws Exception on error
|
||||
*/
|
||||
@Test
|
||||
public void testStringSignature() throws Exception
|
||||
{
|
||||
final Arg ARG_STR = new Arg(String.class);
|
||||
|
||||
DynamicArgs.Builder dab = new DynamicArgs.Builder();
|
||||
dab.addSignature(ARG_STR);
|
||||
|
||||
final Arg CALL_STR = new Arg(String.class);
|
||||
|
||||
SampleSignatures samples = new SampleSignatures();
|
||||
Method m = findMethodByName(samples, "sigStr");
|
||||
DynamicArgs dynamicArgs = dab.build(m, CALL_STR);
|
||||
assertThat("DynamicArgs", dynamicArgs, notNullValue());
|
||||
|
||||
// Test with potential args
|
||||
String result = (String) dynamicArgs.invoke(samples, "Hello");
|
||||
assertThat("result", result, is("sigStr<Hello>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of finding a match on a method that is tagged
|
||||
* via the ArgIdentifier concepts.
|
||||
*
|
||||
* @throws Exception on error
|
||||
*/
|
||||
@Test
|
||||
public void testByteArraySignature() throws Exception
|
||||
{
|
||||
final Arg ARG_BYTEARRAY = new Arg(byte[].class);
|
||||
final Arg ARG_OFFSET = new Arg(int.class).setTag("offset");
|
||||
final Arg ARG_LENGTH = new Arg(int.class).setTag("length");
|
||||
|
||||
DynamicArgs.Builder dab = new DynamicArgs.Builder();
|
||||
dab.addSignature(ARG_BYTEARRAY, ARG_OFFSET, ARG_LENGTH);
|
||||
|
||||
SampleSignatures ssigs = new SampleSignatures();
|
||||
Method m = findMethodByName(ssigs, "sigByteArray");
|
||||
DynamicArgs dynamicArgs = dab.build(m, ARG_BYTEARRAY, ARG_OFFSET, ARG_LENGTH);
|
||||
assertThat("DynamicArgs", dynamicArgs, notNullValue());
|
||||
|
||||
// Test with potential args
|
||||
byte buf[] = new byte[222];
|
||||
int offset = 3;
|
||||
int len = 44;
|
||||
String result = (String) dynamicArgs.invoke(ssigs, buf, offset, len);
|
||||
assertThat("result", result, is("sigByteArray<[222],3,44>"));
|
||||
|
||||
// Test with empty potential args
|
||||
result = (String) dynamicArgs.invoke(ssigs, null, 123, 456);
|
||||
assertThat("result", result, is("sigByteArray<<null>,123,456>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of calling a method with 2 custom objects
|
||||
*
|
||||
* @throws Exception on error
|
||||
*/
|
||||
@Test
|
||||
public void testObjects_A_B() throws Exception
|
||||
{
|
||||
final Arg ARG_A = new Arg(A.class);
|
||||
final Arg ARG_B = new Arg(B.class);
|
||||
|
||||
DynamicArgs.Builder dab = new DynamicArgs.Builder();
|
||||
dab.addSignature(ARG_A, ARG_B);
|
||||
|
||||
SampleSignatures ssigs = new SampleSignatures();
|
||||
Method m = findMethodByName(ssigs, "sigObjectArgs");
|
||||
DynamicArgs dynamicArgs = dab.build(m, ARG_A, ARG_B);
|
||||
assertThat("DynamicArgs", dynamicArgs, notNullValue());
|
||||
|
||||
// Test with potential args
|
||||
A a = new A("foo");
|
||||
B b = new B(444);
|
||||
String result = (String) dynamicArgs.invoke(ssigs, a, b);
|
||||
assertThat("result", result, is("sigObjectArgs<A:foo,B:444>"));
|
||||
|
||||
// Test with null potential args
|
||||
result = (String) dynamicArgs.invoke(ssigs, null, b);
|
||||
assertThat("result", result, is("sigObjectArgs<<null>,B:444>"));
|
||||
|
||||
result = (String) dynamicArgs.invoke(ssigs, a, null);
|
||||
assertThat("result", result, is("sigObjectArgs<A:foo,<null>>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of calling a method with 2 custom objects, but the method only has 1 declared
|
||||
*
|
||||
* @throws Exception on error
|
||||
*/
|
||||
@Test
|
||||
public void testObjects_A() throws Exception
|
||||
{
|
||||
final Arg ARG_A = new Arg(A.class);
|
||||
final Arg ARG_B = new Arg(B.class);
|
||||
|
||||
DynamicArgs.Builder dab = new DynamicArgs.Builder();
|
||||
dab.addSignature(ARG_A, ARG_B);
|
||||
|
||||
SampleSignatures ssigs = new SampleSignatures();
|
||||
Method m = findMethodByName(ssigs, "sigObjectA");
|
||||
DynamicArgs dynamicArgs = dab.build(m, ARG_A, ARG_B);
|
||||
assertThat("DynamicArgs", dynamicArgs, notNullValue());
|
||||
|
||||
// Test with potential args
|
||||
A a = new A("foo");
|
||||
B b = new B(555);
|
||||
String result = (String) dynamicArgs.invoke(ssigs, a, b);
|
||||
assertThat("result", result, is("sigObjectA<A:foo>"));
|
||||
|
||||
// Test with null potential args
|
||||
result = (String) dynamicArgs.invoke(ssigs, null, b);
|
||||
assertThat("result", result, is("sigObjectA<<null>>"));
|
||||
|
||||
result = (String) dynamicArgs.invoke(ssigs, a, null);
|
||||
assertThat("result", result, is("sigObjectA<A:foo>"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of calling a method with 2 custom objects, but the method only has 1 declared
|
||||
*
|
||||
* @throws Exception on error
|
||||
*/
|
||||
@Test
|
||||
public void testObjects_B() throws Exception
|
||||
{
|
||||
final Arg ARG_A = new Arg(A.class);
|
||||
final Arg ARG_B = new Arg(B.class);
|
||||
|
||||
DynamicArgs.Builder dab = new DynamicArgs.Builder();
|
||||
dab.addSignature(ARG_A, ARG_B);
|
||||
|
||||
SampleSignatures ssigs = new SampleSignatures();
|
||||
Method m = findMethodByName(ssigs, "sigObjectB");
|
||||
DynamicArgs dynamicArgs = dab.build(m, ARG_A, ARG_B);
|
||||
assertThat("DynamicArgs", dynamicArgs, notNullValue());
|
||||
|
||||
// Test with potential args
|
||||
A a = new A("foo");
|
||||
B b = new B(666);
|
||||
String result = (String) dynamicArgs.invoke(ssigs, a, b);
|
||||
assertThat("result", result, is("sigObjectB<B:666>"));
|
||||
|
||||
// Test with null potential args
|
||||
result = (String) dynamicArgs.invoke(ssigs, null, b);
|
||||
assertThat("result", result, is("sigObjectB<B:666>"));
|
||||
|
||||
result = (String) dynamicArgs.invoke(ssigs, a, null);
|
||||
assertThat("result", result, is("sigObjectB<<null>>"));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue