Class DuckWrapper
- java.lang.Object
-
- com.identityworksllc.iiq.common.DuckWrapper
-
- All Implemented Interfaces:
InvocationHandler
public class DuckWrapper extends Object implements InvocationHandler
Proxy wrapper for duck typing in Java.Duck typing is named for the old saying that ‘if it quacks like a duck, it must be a duck’. In dynamically typed languages like JavaScript, method handles are resolved at runtime so any object implementing the appropriate methods can be used.
This class creates a
Proxy
that forwards interface methods to the given wrapped object. This allows you to ‘fake’ an interface implementation where you don’t have control over the class’s source code.If the object being wrapped doesn’t have a method matching something in your interface, it will just be ignored. Invoking the method will always return null with any arguments.
Some examples:
-
Many SailPointObjects have a getAttributes(), but those classes don’t implement a common interface. As a developer, you don’t have access to modify SailPoint’s API classes. To simplify your own code, you could create an AttributesContainer interface and use this class to coerce the SailPointObject to that interface.
-
IIQ has two different nearly-identical versions of WebServicesClient. One is inaccessible except through the connector classloader. You could construct an instance of the inaccessible client class, exposing any relevant methods to your application via your own interface.
-
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description Object
invoke(Object proxy, Method method, Object[] args)
Invokes the optional callback, and then the method on the wrapped object, in that order.static <T> T
wrap(Class<? super T> intf, Object input)
Wraps the given object so that it appears to implement the given interface.static <T> T
wrap(Class<? super T> intf, Object input, BiConsumer<Method,MethodHandle> callback)
Wraps the given object in the given interface.
-
-
-
Method Detail
-
wrap
public static <T> T wrap(Class<? super T> intf, Object input) throws sailpoint.tools.GeneralException
Wraps the given object so that it appears to implement the given interface.Any calls to the interface methods will forward to the most appropriate method on the object.
- Type Parameters:
T
- The resulting type- Parameters:
intf
- The interface the resulting proxy needs to implementinput
- The target object to be wrapped within the proxy- Returns:
- A proxy to the underlying object that appears to implement the given interface
- Throws:
sailpoint.tools.GeneralException
- if any failures occur establishing the proxy
-
wrap
public static <T> T wrap(Class<? super T> intf, Object input, BiConsumer<Method,MethodHandle> callback) throws sailpoint.tools.GeneralException
Wraps the given object in the given interface.Any calls to the interface methods will forward to the object.
- Type Parameters:
T
- The resulting type- Parameters:
intf
- The interface the resulting proxy needs to implementinput
- The target object to be wrapped within the proxycallback
- An optional callback that will be invoked for every method called (for testing)- Returns:
- A proxy to the underlying object that appears to implement the given interface
- Throws:
sailpoint.tools.GeneralException
- if any failures occur establishing the proxy
-
invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
Invokes the optional callback, and then the method on the wrapped object, in that order.If the method handle didn’t match (i.e., your interface has a method not matched in the wrapped object), this will return null without failing.
- Specified by:
invoke
in interfaceInvocationHandler
- Throws:
Throwable
- See Also:
InvocationHandler.invoke(Object, Method, Object[])
-
-