com.versionone.utils.Delegator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of VersionOne.SDK.Java.APIClient Show documentation
Show all versions of VersionOne.SDK.Java.APIClient Show documentation
A library for custom Java development against the VersionOne Development Platform's REST API.
package com.versionone.utils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
/**
* Delegator class from the article
* http://www.onjava.com/pub/a/onjava/2003/05/21/delegates.html?page=1
*
* Class representing a delegate template -
* also a factory returning the real delegate object
*
* @author Steve Lewis [email protected]
*/
@SuppressWarnings("unchecked")
public class Delegator {
public static final Method[] EMPTY_METHOD_ARRAY = {};
public static final Object[] EMPTY_OBJECT_ARRAY = {};
public static final Delegator[] EMPTY_ARRAY = {};
// convenience implementation
public static final Delegator RUNNABLE_DELEGATE = new Delegator(Runnable.class);
/**
* Convenience method to make a runnable delegate
*
* @param item non-null target object
* @param methodName non-null name of a method of type void ()
* @return non-null Runnable proxy
*/
public static Runnable buildRunnable(Object item, String methodName) {
return ((Runnable) RUNNABLE_DELEGATE.build(item, methodName));
}
/**
* Convenience method to make a runnable delegate
*
* @param item non-null target class
* @param methodName non-null name of a method of type void ()
* @return non-null Runnable proxy
*/
public static Runnable buildRunnable(Class item, String methodName) {
return ((Runnable) RUNNABLE_DELEGATE.build(item, methodName));
}
private final Class m_Interface; // may be null
private final Class m_Return;
private final Class[] m_Arguments;
/**
* @param params non-null array of arguments
* @param retClass possibly null return class null says do not care
*/
public Delegator(Class[] params, Class retClass) {
m_Interface = null;
m_Return = retClass;
m_Arguments = params;
}
/**
* @param TheInterface an non-null interface with EXACTLY one method
*/
public Delegator(Class TheInterface) {
m_Interface = TheInterface;
Method met = findMethod(TheInterface);
m_Return = met.getReturnType();
m_Arguments = met.getParameterTypes();
}
/**
* accessor for return class
* @return class - Class
*/
public Class getReturn() {
return m_Return;
}
/**
* accessor for argument classes
* @return class - Class[]
*/
public Class[] getArguments() {
return m_Arguments;
}
public Class getInterface() {
return m_Interface;
}
/**
* @param target non-null class with a bindable static method
* @param MethodName name of the static method
* @return non-null IDelegate if getInterface() is non-null it will be a dynamic proxy implementing that interface
*/
public IDelegate build(Class target, String MethodName) {
Class myInterface = getInterface();
DelegateProxy theDelegate = new DelegateProxy(null, target, MethodName, this);
if (myInterface != null) {
Class[] interfaces = {myInterface, IDelegate.class};
IDelegate ret = (IDelegate) java.lang.reflect.Proxy.newProxyInstance(
target.getClassLoader(),
interfaces, theDelegate);
return ret;
}
return theDelegate;
}
/**
* @param target non-null target with a bindable method
* @param MethodName name of the method
* @return non-null IDelegate if getInterface() is non-null it will be a dynamic proxy implementing that interface
*/
public IDelegate build(Object target, String MethodName) {
Class myInterface = getInterface();
DelegateProxy theDelegate = new DelegateProxy(target, target.getClass(), MethodName, this);
if (myInterface != null) { // build a dynamic proxy
Class[] interfaces = {myInterface, IDelegate.class};
IDelegate ret = (IDelegate) java.lang.reflect.Proxy.newProxyInstance(
target.getClass().getClassLoader(),
interfaces, theDelegate);
return (ret);
}
if (!(theDelegate instanceof IDelegate)) {
throw new ClassCastException();
}
return theDelegate;
}
protected class DelegateProxy implements IDelegate, InvocationHandler {
private final Method m_Method;
private final Object m_Target;
@SuppressWarnings("unused")
private final Delegator m_Template;
/**
* constructor supplying a Class passing in types not template
*
* @param target possibly null target if null the method must be static
* @param targetClass non-null class implementing a suitable method
* @param methodName nun-null name of a public static method in target
* @param template non-null template with the required arguemts and return
*/
protected DelegateProxy(Object target, Class targetClass, String methodName, Delegator template) {
m_Template = template;
m_Target = target;
m_Method = findSuitableMethod(targetClass, methodName, template);
}
/**
* convenience call to handle case of no arguments
*
* @return Object
*/
public Object invoke() throws IllegalArgumentException, DelegateInvokeException {
return invoke(EMPTY_OBJECT_ARRAY);
}
/**
* convenience call to handle case of one argument
*
* @param arg some argument
* @return Object
*/
public Object invoke(Object arg) throws IllegalArgumentException, DelegateInvokeException {
Object[] args = {arg};
return invoke(args);
}
/**
* convenience call to handle case of two argument
*
* @param arg1 some argument
* @param arg2 some argument
* @return Object
*/
public Object invoke(Object arg1, Object arg2) throws IllegalArgumentException, DelegateInvokeException {
Object[] args = {arg1, arg2};
return invoke(args);
}
/**
* method required by InvocationHandler so we can build dynamic Proxys
*
* @param proxy object for which we are a proxy (ignored)
* @param method method to call (ignored)
* @param args arguments to pass
* @return Object - primitive types are wrapped
*/
public Object invoke(Object proxy, Method method, Object[] args) {
return invoke(args);
}
/**
* basic call to method
*
* @param args method arguments
* @return Object
*/
public Object invoke(Object[] args) throws IllegalArgumentException, DelegateInvokeException {
// validateArgs(args);
try {
Object ret = getMethod().invoke(getTarget(), args);
return ret;
} catch (IllegalAccessException ex) {
throw new IllegalStateException("Bad Delegate State: " + ex.getMessage()); // should not happen
} catch (InvocationTargetException ex) {
throw new Delegator.DelegateInvokeException(ex.getCause());
}
}
/**
* if uncommented in invoke this code will throw an IllegalArgument call
* if arguments are of the wrong type
* @param args - Object
* @throws IllegalArgumentException - IllegalArgumentException
*/
protected void validateArgs(Object[] args) throws IllegalArgumentException {
Class[] MyArgs = getArguments();
if (args.length != MyArgs.length) {
throw new IllegalArgumentException("Delegate required " + MyArgs.length + "arguments");
}
for (int i = 0; i < args.length; i++) {
if (!MyArgs[i].isInstance(args[i])) {
throw new IllegalArgumentException("Argument " + i + " must be of class " + MyArgs[i].getName());
}
}
}
/**
* accessor for the method
* @return Method - Method
*/
public Method getMethod() {
return m_Method;
}
/**
* accessor for the target
* @return Object - Object
*/
public Object getTarget() {
return m_Target;
}
}// end class DelegateProxy
/**
* All problems become this type of exception
* As a runtime we do not impose burdens on the calling code
*/
public static class DelegateInvokeException extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 1L;
public DelegateInvokeException(Throwable cause) {
super(cause);
}
}
// ===================================================================
// static utility methods in this section identify the
// method in verious targets
// ===================================================================
/**
* utility method to test suitability
* @param args - Class[]
* @param retClass - Class
* @param testMethod - Method
* @return boolean - boolean
*/
protected static boolean isSuitableMethod(Method testMethod, Class[] args, Class retClass) {
Class[] methodArgs = testMethod.getParameterTypes();
for (int i = 0; i < methodArgs.length; i++) {
Class arg = methodArgs[i];
if (!arg.isAssignableFrom(args[i])) {
return false;
}
}
// This is the only
isValidReturn(testMethod, retClass);
return (true);
}
/**
* utility method to get candidate methods to search
* @param MethodName - String
* @param nargs - int
* @param targetClass - Class
* @return Method - Method[]
*/
protected static Method[] getCandidateMethods(Class targetClass, String MethodName, int nargs) {
Method[] possibilities = targetClass.getMethods();
List holder = new ArrayList();
for (int i = 0; i < possibilities.length; i++) {
Method possibility = possibilities[i];
if (possibility.getName().equals(MethodName) &&
possibility.getParameterTypes().length == nargs &&
Modifier.isPublic(possibility.getModifiers())) {
holder.add(possibility);
}
}
return (Method[]) holder.toArray(EMPTY_METHOD_ARRAY);
}
/**
* utility method to test return
* @param retClass - Class
* @param test - Method
* @return boolean - boolean
*/
protected static boolean isValidReturn(Method test, Class retClass) {
if (retClass == null) {
return true; // we do not care
}
if (test.getReturnType() == retClass) {
return true;
}
if (retClass.isAssignableFrom(test.getReturnType())) {
return true;
}
return (false);
}
/**
* Utility method to locate a proper Method object
* @param targetClass - Class
* @param MethodName - String
* @param templ - Delegator
* @return Method - Method
*/
protected static Method findSuitableMethod(Class targetClass, String MethodName, Delegator templ) {
Class[] args = templ.getArguments();
Class retClass = templ.getReturn();
// perfect match
try {
Method ret = targetClass.getMethod(MethodName, args);
if (!isValidReturn(ret, retClass)) {
throw new IllegalArgumentException("Requested method returns wrong type");
}
if (!Modifier.isPublic(ret.getModifiers())) {
throw new IllegalArgumentException("Requested method is not public");
}
return ret;
} catch (Exception ex) {
} // on to try2
Method[] possibilities = getCandidateMethods(targetClass, MethodName, args.length);
for (int i = 0; i < possibilities.length; i++) {
Method possibility = possibilities[i];
if (isSuitableMethod(possibility, args, retClass)) {
return possibility;
}
}
throw new IllegalArgumentException("No suitable method found");
}
/**
* utility code to find the one suitable method in the passed in interface.
* @param TheInterface - Class
* @return Method - Method
*/
protected static Method findMethod(Class TheInterface) {
if (!TheInterface.isInterface()) {
throw new IllegalArgumentException("DelegateTemplate must be constructed with an interface");
}
Method[] methods = TheInterface.getMethods();
Method ret = null;
for (int i = 0; i < methods.length; i++) {
Method test = methods[i];
if (Modifier.isAbstract(test.getModifiers())) {
if (ret != null) {
throw new IllegalArgumentException("DelegateTemplate must be constructed with an interface implementing only one method!");
}
ret = test;
}
}
if (ret == null) {
throw new IllegalArgumentException("DelegateTemplate must be constructed with an interface implementing exactly method!");
}
return ret;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy