package org.jbpm.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.logging.Logger;
import org.jbpm.wire.descriptor.ArgDescriptor;
public abstract class ReflectUtil {
private static Logger log = Logger.getLogger(ReflectUtil.class.getName());
public static Class loadClass(ClassLoader classLoader, String className) {
try {
return classLoader.loadClass(className);
} catch (NoClassDefFoundError e) {
throw new JbpmReflectException("couldn't define class "+className, e);
} catch (ClassNotFoundException e) {
throw new JbpmReflectException("couldn't load class "+className, e);
}
}
public static Object instantiate(ClassLoader classLoader, String className) {
Object newObject;
try {
Class clazz = loadClass(classLoader, className);
newObject = clazz.newInstance();
} catch (Exception e) {
throw new JbpmReflectException("couldn't instantiate "+className, e);
}
return newObject;
}
public static Class[] loadClasses(ClassLoader classLoader, List<String> constructorArgTypeNames) {
if (constructorArgTypeNames==null) return null;
Class[] classes = new Class[constructorArgTypeNames.size()];
for (int i=0; i<constructorArgTypeNames.size(); i++) {
classes[i] = loadClass(classLoader, constructorArgTypeNames.get(i));
}
return classes;
}
public static Constructor getConstructor(Class clazz, Class[] parameterTypes) {
Constructor constructor = null;
try {
constructor = clazz.getDeclaredConstructor(parameterTypes);
} catch (SecurityException e) {
throw new JbpmReflectException("wasn't allowed to get constructor '"+clazz.getName()+"("+getParameterTypesText(parameterTypes)+")'", e);
} catch (NoSuchMethodException e) {
throw new JbpmReflectException("couldn't find constructor '"+clazz.getName()+"("+getParameterTypesText(parameterTypes)+")'", e);
}
constructor.setAccessible(true);
return constructor;
}
public static Field getField(Class clazz, String fieldName) {
return getField(clazz, fieldName, clazz);
}
private static Field getField(Class clazz, String fieldName, Class original) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
} catch (SecurityException e) {
throw new JbpmReflectException("wasn't allowed to get field '"+clazz.getName()+"."+fieldName+"'", e);
} catch (NoSuchFieldException e) {
if (clazz.getSuperclass()!=null) {
return getField(clazz.getSuperclass(), fieldName, original);
} else {
throw new JbpmReflectException("couldn't find field '"+original.getName()+"."+fieldName+"'", e);
}
}
field.setAccessible(true);
return field;
}
public static Method getMethod(Class clazz, String methodName, Class[] parameterTypes) {
return getMethod(clazz, methodName, parameterTypes, clazz);
}
private static Method getMethod(Class clazz, String methodName, Class[] parameterTypes, Class original) {
Method method = null;
try {
method = clazz.getDeclaredMethod(methodName, parameterTypes);
} catch (SecurityException e) {
throw new JbpmReflectException("wasn't allowed to get method '"+clazz.getName()+"."+methodName+"("+getParameterTypesText(parameterTypes)+")'", e);
} catch (NoSuchMethodException e) {
if (clazz.getSuperclass()!=null) {
return getMethod(clazz.getSuperclass(), methodName, parameterTypes, original);
} else {
throw new JbpmReflectException("couldn't find method '"+original.getName()+"."+methodName+"("+getParameterTypesText(parameterTypes)+")'", e);
}
}
method.setAccessible(true);
return method;
}
private static String getParameterTypesText(Class[] parameterTypes) {
if (parameterTypes==null) return "";
StringBuffer parametersTypeText = new StringBuffer();
for (int i=0; i<parameterTypes.length; i++) {
Class parameterType = parameterTypes[i];
parametersTypeText.append(parameterType.getName());
if (i!=parameterTypes.length-1) {
parametersTypeText.append(", ");
}
}
return parametersTypeText.toString();
}
public static Object newInstance(Class clazz) {
return newInstance(clazz, null, null);
}
public static Object newInstance(Constructor constructor) {
return newInstance(null, constructor, null);
}
public static Object newInstance(Constructor constructor, Object[] args) {
return newInstance(null, constructor, args);
}
private static Object newInstance(Class clazz, Constructor constructor, Object[] args) {
if ( (clazz==null)
&& (constructor==null)
) {
throw new IllegalArgumentException("can't create new instance without clazz or constructor");
}
String className = null;
try {
if (constructor==null) {
className = clazz.getName();
log.finest("creating new instance for class '"+className+"'");
return clazz.newInstance();
}
className = constructor.getDeclaringClass().getName();
log.finest("creating new instance for class '"+className+"' with args "+ArrayUtil.toString(args));
return constructor.newInstance(args);
} catch (Throwable t) {
throw new JbpmReflectException("couldn't construct new '"+className+"' with args "+ArrayUtil.toString(args), t);
}
}
public static Object get(Field field, Object object) {
if (field==null) {
throw new NullPointerException("field is null");
}
try {
Object value = field.get(object);
log.finest("got value '"+value+"' from field '"+field.getName()+"'");
return value;
} catch (Exception e) {
throw new JbpmReflectException("couldn't get '"+field.getName()+"'", e);
}
}
public static void set(Field field, Object object, Object value) {
if (field==null) {
throw new NullPointerException("field is null");
}
try {
log.finest("setting field '"+field.getName()+"' to value '"+value+"'");
field.setAccessible(true);
field.set(object, value);
} catch (Exception e) {
throw new JbpmReflectException("couldn't set '"+field.getName()+"' to '"+value+"'", e);
}
}
public static Object invoke(Method method, Object target, Object[] args) {
if (method==null) {
throw new JbpmReflectException("method is null");
}
try {
log.finest("invoking '"+method.getName()+"' on '"+target+"' with "+ArrayUtil.toString(args));
method.setAccessible(true);
return method.invoke(target, args);
} catch (InvocationTargetException e) {
Throwable targetException = e.getTargetException();
throw new JbpmReflectException("couldn't invoke '"+method.getName()+"' with "+ArrayUtil.toString(args)+" on "+target+": "+targetException.getMessage(), targetException);
} catch (Exception e) {
throw new JbpmReflectException("couldn't invoke '"+method.getName()+"' with "+ArrayUtil.toString(args)+" on "+target+": "+e.getMessage(), e);
}
}
public static Method findMethod(Class clazz, String methodName, List<ArgDescriptor> argDescriptors, Object[] args) {
Method method = null;
Method[] candidates = clazz.getDeclaredMethods();
for (int i=0; ( (i<candidates.length)
&& (method==null) ); i++) {
Method candidate = candidates[i];
if ( (candidate.getName().equals(methodName))
&& (isArgumentMatch(candidate.getParameterTypes(), argDescriptors, args))
) {
method = candidate;
}
}
if ( (method==null)
&& (clazz.getSuperclass()!=null)
) {
method = findMethod(clazz.getSuperclass(), methodName, argDescriptors, args);
}
if (method!=null) {
method.setAccessible(true);
}
return method;
}
public static Constructor findConstructor(Class clazz, List<ArgDescriptor> argDescriptors, Object[] args) {
Constructor constructor = null;
Constructor[] constructors = clazz.getDeclaredConstructors();
for (int i=0; ( (i<constructors.length)
&& (constructor==null)
); i++) {
if (isArgumentMatch(constructors[i].getParameterTypes(), argDescriptors, args)) {
constructor = constructors[i];
}
}
return constructor;
}
public static boolean isArgumentMatch(Class[] parameterTypes, List<ArgDescriptor> argDescriptors, Object[] args) {
int nbrOfArgs = 0;
if (args!=null) nbrOfArgs = args.length;
int nbrOfParameterTypes = 0;
if (parameterTypes!=null) nbrOfParameterTypes = parameterTypes.length;
if ( (nbrOfArgs==0)
&& (nbrOfParameterTypes==0)
) {
return true;
}
if (nbrOfArgs!=nbrOfParameterTypes) {
return false;
}
for (int i=0; (i<parameterTypes.length); i++) {
Class<?> parameterType = parameterTypes[i];
String argTypeName = (argDescriptors!=null ? argDescriptors.get(i).getTypeName() : null);
if (argTypeName!=null) {
if (! argTypeName.equals(parameterType.getName())) {
return false;
}
} else if ( (args[i]!=null)
&& (! parameterType.isAssignableFrom(args[i].getClass()))
) {
return false;
}
}
return true;
}
public static String getSignature(String methodName, List<ArgDescriptor> argDescriptors, Object[] args) {
String signature = methodName+"(";
if (args!=null) {
for (int i=0; i<args.length; i++) {
String argType = null;
if (argDescriptors!=null) {
ArgDescriptor argDescriptor = argDescriptors.get(i);
if ( (argDescriptor!=null)
&& (argDescriptor.getTypeName()!=null)
) {
argType = argDescriptor.getTypeName();
}
}
if ( (argType==null)
&& (args[i]!=null)
) {
argType = args[i].getClass().getName();
}
signature += argType;
if (i<(args.length-1)) {
signature += ", ";
}
}
}
signature+=")";
return signature;
}
public static String getUnqualifiedClassName(Class<?> clazz) {
if (clazz==null) {
return null;
}
return getUnqualifiedClassName(clazz.getName());
}
public static String getUnqualifiedClassName(String className) {
if (className==null) {
return null;
}
int dotIndex = className.lastIndexOf('.');
if (dotIndex!=-1) {
className = className.substring(dotIndex+1);
}
return className;
}
}