|
package csharp;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.CtPrimitiveType;
import javassist.Modifier;
import javassist.NotFoundException;
public abstract class Delegate {
private static final Map<Integer, Class<? extends Delegate>> instanceDelegates = new ConcurrentHashMap<Integer, Class<? extends Delegate>>();
private static final Map<Integer, Delegate> staticDelegates = new ConcurrentHashMap<Integer, Delegate>();
protected Object object = null;
protected Delegate() {
}
public static <T extends Delegate> T getInstance(
Class<? extends Delegate> delClazz, Class clazz, String name) {
try {
int key = Math
.abs((delClazz.getCanonicalName() + "_" + clazz.getCanonicalName() + "_static")
.hashCode());
Delegate delegate = staticDelegates.get(key);
if (delegate == null) {
Class<? extends Delegate> actualClazz = createClass(delClazz,
name, key, clazz, true);
delegate = actualClazz.newInstance();
staticDelegates.put(key, delegate);
}
return (T) delegate;
} catch (InstantiationException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (SecurityException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
public static <T extends Delegate> T getInstance(
Class<? extends Delegate> delClazz, Object object, String name) {
try {
int key = Math.abs((delClazz.getCanonicalName() + "_"
+ object.getClass().getCanonicalName() + "_instance").hashCode());
Class<? extends Delegate> actualClazz = instanceDelegates.get(key);
if (actualClazz == null) {
actualClazz = createClass(delClazz, name, key,
object.getClass(), false);
instanceDelegates.put(key, actualClazz);
}
Delegate delegate = actualClazz.newInstance();
delegate.object = object;
return (T) delegate;
} catch (InstantiationException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (SecurityException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
private static Class<? extends Delegate> createClass(
Class<? extends Delegate> delClazz, String name, int key,
Class clazz, boolean isStatic) throws SecurityException,
NoSuchMethodException {
try {
Class<? extends Delegate> actualClazz;
ClassPool pool = ClassPool.getDefault();
CtClass newClass = pool.makeClass(clazz.getPackage().getName()
+ ".D" + key);
CtClass sup = pool.get(delClazz.getCanonicalName());
newClass.setSuperclass(sup);
Method[] methods = delClazz.getDeclaredMethods();
Method method = null;
for (Method m : methods) {
if (m.getName().equals("invoke")) {
if (method != null) {
throw new IllegalStateException(delClazz.getCanonicalName()
+ " contains two or more invoke methods.");
}
method = m;
if (m.getModifiers() != 1025) {
throw new IllegalStateException(
delClazz.getCanonicalName()
+ " required invoke method as 'public abstract ");
}
}
}
if (method == null) {
throw new NullPointerException(delClazz.getCanonicalName()
+ " does not have invoke method.");
}
StringBuilder params = new StringBuilder();
StringBuilder values = new StringBuilder();
StringBuilder paramTypes = new StringBuilder();
Class[] parameterTypes = method.getParameterTypes();
int i = 97;
for (Class parameterType : parameterTypes) {
if (params.length() != 0) {
params.append(",");
values.append(",");
paramTypes.append(",");
}
params.append(parameterType.getCanonicalName() + " "
+ new Character((char) i));
values.append(new Character((char) i));
paramTypes.append(parameterType.getCanonicalName() + ".class");
i++;
}
Method objectMethod = clazz.getDeclaredMethod(name, parameterTypes);
StringBuilder exceptions = new StringBuilder();
if (!Modifier.isPrivate(objectMethod.getModifiers())) {
Class[] exceptionTypes = method.getExceptionTypes();
for (Class exceptionType : exceptionTypes) {
if (exceptions.length() != 0) {
exceptions.append(",");
}
exceptions.append(exceptionType.getCanonicalName());
}
} else {
exceptions.append("java.lang.Exception");
}
String body = "public "
+ method.getReturnType().getCanonicalName()
+ " invoke("
+ params.toString()
+ ")"
+ ((exceptions.length() != 0) ? " throws "
+ exceptions.toString() : "") + " {";
if (!Modifier.isPrivate(objectMethod.getModifiers())) {
body += ((!method.getReturnType().getCanonicalName()
.equals("void")) ? "return " : "")
+ ((isStatic) ? clazz.getCanonicalName() : "(("
+ clazz.getCanonicalName() + ")object)")
+ "."
+ name
+ "(" + values.toString() + ");";
} else {
StringBuilder ps = new StringBuilder(
"java.util.List ps = new java.util.ArrayList();");
if (parameterTypes.length != 0) {
for (String s : paramTypes.toString().split(",")) {
ps.append("ps.add(" + s + ");");
}
}
StringBuilder vs = new StringBuilder(
"java.util.List vs = new java.util.ArrayList();");
if (parameterTypes.length != 0) {
i = 0;
for (String s : values.toString().split(",")) {
if (parameterTypes[i].isPrimitive()) {
CtPrimitiveType primitiveType = (CtPrimitiveType) pool
.get(parameterTypes[i].getCanonicalName());
vs.append("vs.add("
+ primitiveType.getWrapperName()
+ ".valueOf(" + s + "));");
} else {
vs.append("vs.add(" + s + ");");
}
i++;
}
}
body += "try {" + ps.toString() + vs.toString()
+ "java.lang.reflect.Method method = "
+ clazz.getCanonicalName() + ".class.getDeclaredMethod(\""
+ name
+ "\",(Class[])ps.toArray(new Class[ps.size()]));"
+ "method.setAccessible(true);" + "method.invoke("
+ ((isStatic) ? "null" : "object") + ",vs.toArray())"
+ ";} catch (java.lang.Exception e) {throw e;}";
}
body += "}";
CtMethod m = CtNewMethod.make(body, newClass);
newClass.addMethod(m);
actualClazz = newClass.toClass();
return actualClazz;
} catch (NotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (CannotCompileException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.