package com.jwmsolutions.jwmscript;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.HashSet;
import java.util.Set;
public class ClassWrapper {
public Class<Object> wrappedClass;
public ClassWrapper(Class cls) {
this.wrappedClass = cls;
}
public Class<Object> getWrappedClass() {
return wrappedClass;
}
public void setWrappedClass(Class<Object> wrappedClass) {
this.wrappedClass = wrappedClass;
}
public Class asSubclass(Class arg0) {
return wrappedClass.asSubclass(arg0);
}
public Object cast(Object arg0) {
return wrappedClass.cast(arg0);
}
public boolean desiredAssertionStatus() {
return wrappedClass.desiredAssertionStatus();
}
public boolean equals(Object arg0) {
return wrappedClass.equals(arg0);
}
public Annotation getAnnotation(Class arg0) {
return wrappedClass.getAnnotation(arg0);
}
public Annotation[] getAnnotations() {
return wrappedClass.getAnnotations();
}
public String getCanonicalName() {
return wrappedClass.getCanonicalName();
}
public Class[] getClasses() {
return wrappedClass.getClasses();
}
public ClassLoader getClassLoader() {
return wrappedClass.getClassLoader();
}
public Class getComponentType() {
return wrappedClass.getComponentType();
}
public Constructor<Object> getConstructor(Class... arg0)
throws NoSuchMethodException, SecurityException {
return wrappedClass.getConstructor(arg0);
}
public Constructor[] getConstructors() throws SecurityException {
return wrappedClass.getConstructors();
}
public Annotation[] getDeclaredAnnotations() {
return wrappedClass.getDeclaredAnnotations();
}
public Class[] getDeclaredClasses() throws SecurityException {
return wrappedClass.getDeclaredClasses();
}
public Constructor<Object> getDeclaredConstructor(Class... arg0)
throws NoSuchMethodException, SecurityException {
return wrappedClass.getDeclaredConstructor(arg0);
}
public Constructor[] getDeclaredConstructors() throws SecurityException {
return wrappedClass.getDeclaredConstructors();
}
public Field getDeclaredField(String arg0) throws NoSuchFieldException,
SecurityException {
return wrappedClass.getDeclaredField(arg0);
}
public Field[] getDeclaredFields() throws SecurityException {
return wrappedClass.getDeclaredFields();
}
public Method getDeclaredMethod(String arg0, Class... arg1)
throws NoSuchMethodException, SecurityException {
return wrappedClass.getDeclaredMethod(arg0, arg1);
}
public Method[] getDeclaredMethods() throws SecurityException {
return wrappedClass.getDeclaredMethods();
}
public Class getDeclaringClass() {
return wrappedClass.getDeclaringClass();
}
public Class getEnclosingClass() {
return wrappedClass.getEnclosingClass();
}
public Constructor getEnclosingConstructor() {
return wrappedClass.getEnclosingConstructor();
}
public Method getEnclosingMethod() {
return wrappedClass.getEnclosingMethod();
}
public Object[] getEnumConstants() {
return wrappedClass.getEnumConstants();
}
public Field getField(String arg0) throws NoSuchFieldException,
SecurityException {
return wrappedClass.getField(arg0);
}
public Field[] getFields() throws SecurityException {
return wrappedClass.getFields();
}
public Type[] getGenericInterfaces() {
return wrappedClass.getGenericInterfaces();
}
public Type getGenericSuperclass() {
return wrappedClass.getGenericSuperclass();
}
public Class[] getInterfaces() {
return wrappedClass.getInterfaces();
}
public Method getMethod(String arg0, Class... arg1)
throws NoSuchMethodException, SecurityException {
return wrappedClass.getMethod(arg0, arg1);
}
public Method[] getMethods() throws SecurityException {
return wrappedClass.getMethods();
}
public int getModifiers() {
return wrappedClass.getModifiers();
}
public String getName() {
return wrappedClass.getName();
}
public Package getPackage() {
return wrappedClass.getPackage();
}
public ProtectionDomain getProtectionDomain() {
return wrappedClass.getProtectionDomain();
}
public URL getResource(String arg0) {
return wrappedClass.getResource(arg0);
}
public InputStream getResourceAsStream(String arg0) {
return wrappedClass.getResourceAsStream(arg0);
}
public Object[] getSigners() {
return wrappedClass.getSigners();
}
public String getSimpleName() {
return wrappedClass.getSimpleName();
}
public Class getSuperclass() {
return wrappedClass.getSuperclass();
}
public TypeVariable[] getTypeParameters() {
return wrappedClass.getTypeParameters();
}
public int hashCode() {
return wrappedClass.hashCode();
}
public boolean isAnnotation() {
return wrappedClass.isAnnotation();
}
public boolean isAnnotationPresent(Class arg0) {
return wrappedClass.isAnnotationPresent(arg0);
}
public boolean isAnonymousClass() {
return wrappedClass.isAnonymousClass();
}
public boolean isArray() {
return wrappedClass.isArray();
}
public boolean isAssignableFrom(Class arg0) {
return wrappedClass.isAssignableFrom(arg0);
}
public boolean isEnum() {
return wrappedClass.isEnum();
}
public boolean isInstance(Object arg0) {
return wrappedClass.isInstance(arg0);
}
public boolean isInterface() {
return wrappedClass.isInterface();
}
public boolean isLocalClass() {
return wrappedClass.isLocalClass();
}
public boolean isMemberClass() {
return wrappedClass.isMemberClass();
}
public boolean isPrimitive() {
return wrappedClass.isPrimitive();
}
public boolean isSynthetic() {
return wrappedClass.isSynthetic();
}
public Object newInstance() throws InstantiationException,
IllegalAccessException {
return wrappedClass.newInstance();
}
public String toString() {
return wrappedClass.toString();
}
public Set<String> getUniqueMethodNames() {
Method[] methods = wrappedClass.getMethods();
Set<String> names = new HashSet<String>();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
names.add(m.getName());
}
return names;
}
public Set<String> getFieldNames() {
Field[] fields = wrappedClass.getFields();
Set<String> names = new HashSet<String>();
for (int i = 0; i < fields.length; i++) {
Field f = fields[i];
names.add(f.getName());
}
return names;
}
public Object getStaticField(String name) throws IllegalArgumentException,
SecurityException, IllegalAccessException, NoSuchFieldException {
return wrappedClass.getDeclaredField(name).get(null);
}
public Object getInstanceField(Object obj, String name)
throws IllegalArgumentException, SecurityException,
IllegalAccessException, NoSuchFieldException {
return wrappedClass.getDeclaredField(name).get(obj);
}
public Object callStaticMethod(String name, Object... arguments)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException {
return callInstanceMethod(null, name, arguments);
}
public Object callInstanceMethod(Object target, String name,
Object... arguments) throws IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Method[] methods = wrappedClass.getMethods();
Method applicableMethod = null;
Object[] coercedArguments = new Object[arguments.length];
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (m.getName().equals(name)) {
Class[] paramTypes = m.getParameterTypes();
if (paramTypes.length == arguments.length) {
int j = 0;
while (j < paramTypes.length) {
if (!argumentMatchType(arguments, paramTypes,
coercedArguments, j)) {
// System.err.println("[class '" + m_class.getName()
// + "' [method '" + name + "'] Failed matching '" +
// arguments[j].getClass() + "' with '" +
// paramTypes[j] + "'");
break;
}
j++;
}
if (j == paramTypes.length) {
if (applicableMethod == null) {
applicableMethod = m;
} else {
throw new NoSuchMethodError(
"More than one method named "
+ name
+ " is applicable on provided arguments");
}
}
}
}
}
if (applicableMethod != null) {
return applicableMethod.invoke(target, coercedArguments);
}
throw new NoSuchMethodError("No method named " + name
+ " is applicable on provided arguments");
}
public Object newInstance(Object... arguments)
throws IllegalArgumentException, InstantiationException,
IllegalAccessException, InvocationTargetException {
Constructor[] constructors = getWrappedClass().getConstructors();
Constructor applicableConstructor = null;
Object[] coercedArguments = new Object[arguments.length];
for (int i = 0; i < constructors.length; i++) {
Constructor c = constructors[i];
Class[] paramTypes = c.getParameterTypes();
if (paramTypes.length == arguments.length) {
int j = 0;
while (j < paramTypes.length) {
if (!argumentMatchType(arguments, paramTypes,
coercedArguments, j)) {
break;
}
j++;
}
if (j == paramTypes.length) {
if (applicableConstructor == null) {
applicableConstructor = c;
} else {
throw new NoSuchMethodError(
"More than one constructor is applicable on provided arguments");
}
}
}
}
if (applicableConstructor != null) {
return applicableConstructor.newInstance(coercedArguments);
}
throw new NoSuchMethodError(
"No constructor is applicable on provided arguments");
}
final static private Class[] s_primitiveTypes = new Class[] { Boolean.TYPE,
Byte.TYPE, Character.TYPE, Double.TYPE, Float.TYPE, Integer.TYPE,
Long.TYPE, Short.TYPE };
final static private Class[] s_primitiveClasses = new Class[] {
Boolean.class, Byte.class, Character.class, Double.class,
Float.class, Integer.class, Long.class, Short.class };
private boolean argumentMatchType(Object[] arguments, Class[] types,
Object[] coercedArguments, int index) {
Object argument = arguments[index];
Class type = types[index];
coercedArguments[index] = argument;
if (argument == null) {
coercedArguments[index] = null;
return true;
} else if (type.isAssignableFrom(argument.getClass())) {
coercedArguments[index] = argument;
return true;
} else if (type.equals(String.class)) {
coercedArguments[index] = argument.toString();
return true;
} else {
if (argument instanceof Double) {
double d = ((Double) argument).doubleValue();
if ((d - ((int) d)) == 0.0) {
coercedArguments[index] = new Integer((int) d);
}
} else if (argument instanceof Float) {
float f = ((Float) argument).floatValue();
if ((f - ((int) f)) == 0) {
coercedArguments[index] = new Integer((int) f);
}
}
if (type.isPrimitive()) {
for (int i = 0; i < s_primitiveClasses.length; i++) {
if (type.equals(s_primitiveTypes[i])) {
type = s_primitiveClasses[i];
break;
}
}
}
return type.isAssignableFrom(coercedArguments[index].getClass());
}
}
}