CtClass map = pool.get("java.util.Map");
CtField methodMap = new CtField(map, "methodMap", proxy);
methodMap.setModifiers(Modifier.PRIVATE | Modifier.STATIC);
Instrumentor.addSyntheticAttribute(methodMap);
proxy.addField(methodMap);
CtMethod getMethodMap = CtNewMethod.getter("getMethodMap", methodMap);
getMethodMap.setModifiers(Modifier.PUBLIC);
Instrumentor.addSyntheticAttribute(getMethodMap);
proxy.addMethod(getMethodMap);
HashSet<String> addedInterfaces = new HashSet<String>();
HashSet<Long> addedMethods = new HashSet<Long>();
if (mixins != null)
{
for (int i = 0; i < mixins.length; i++)
{
HashSet<Long> mixinMethods = new HashSet<Long>();
Class<?>[] mixinf = mixins[i].getInterfaces();
ClassPool mixPool = AspectManager.instance().findClassPool(mixins[i].getMixin().getClass());
CtClass mixClass = mixPool.get(mixins[i].getMixin().getClass().getName());
for (int j = 0; j < mixinf.length; j++)
{
if (addedInterfaces.contains(mixinf[j].getName())) throw new Exception("2 mixins are implementing the same interfaces");
ClassPool mixIntfPool = AspectManager.instance().findClassPool(mixinf[j]);
CtClass intfClass = mixIntfPool.get(mixinf[j].getName());
CtMethod[] methods = intfClass.getMethods();
for (int m = 0; m < methods.length; m++)
{
if (methods[m].getDeclaringClass().getName().equals("java.lang.Object")) continue;
Long hash = new Long(JavassistMethodHashing.methodHash(methods[m]));
if (mixinMethods.contains(hash)) continue;
if (addedMethods.contains(hash)) throw new Exception("More than one mixin has same method");
mixinMethods.add(hash);
addedMethods.add(hash);
String returnStr = (methods[m].getReturnType().equals(CtClass.voidType)) ? "" : "return ";
String code = "{" +
" " + mixClass.getName() + " mixin = (" + mixClass.getName() + ")mixins[" + i + "].getMixin();" +
" " + returnStr + " mixin." + methods[m].getName() + "($$);" +
"}";
CtMethod newMethod = CtNewMethod.make(methods[m].getReturnType(), methods[m].getName(), methods[m].getParameterTypes(), methods[m].getExceptionTypes(), code, proxy);
newMethod.setModifiers(Modifier.PUBLIC);
proxy.addMethod(newMethod);
}
proxy.addInterface(intfClass);
addedInterfaces.add(intfClass.getName());
}
}
}
for (int i = 0; i < interfaces.length; i++)
{
if (addedInterfaces.contains(interfaces[i].getName())) continue;
ClassPool mixPool = AspectManager.instance().findClassPool(interfaces[i]);
CtClass intfClass = mixPool.get(interfaces[i].getName());
CtMethod[] methods = intfClass.getMethods();
for (int m = 0; m < methods.length; m++)
{
if (methods[m].getDeclaringClass().getName().equals("java.lang.Object")) continue;
Long hash = Long.valueOf(JavassistMethodHashing.methodHash(methods[m]));
if (addedMethods.contains(hash)) continue;
addedMethods.add(hash);
String aopReturnStr = (methods[m].getReturnType().equals(CtClass.voidType)) ? "" : "return ($r)";
String args = "null";
if (methods[m].getParameterTypes().length > 0) args = "$args";
String code = "{ " +
" org.jboss.aop.advice.Interceptor[] aspects = instanceAdvisor.getInterceptors(); " +
" org.jboss.aop.MethodInfo mi = new org.jboss.aop.MethodInfo(); " +
" mi.setHash(" + hash.longValue() + "L);" +
" org.jboss.aop.proxy.ProxyMethodInvocation invocation = new org.jboss.aop.proxy.ProxyMethodInvocation(this, mi, aspects); " +
" invocation.setInstanceResolver(instanceAdvisor.getMetaData()); " +
" invocation.setArguments(" + args + "); " +
" " + aopReturnStr + " invocation.invokeNext(); " +
"}";
CtMethod newMethod = CtNewMethod.make(methods[m].getReturnType(), methods[m].getName(), methods[m].getParameterTypes(), methods[m].getExceptionTypes(), code, proxy);
newMethod.setModifiers(Modifier.PUBLIC);
proxy.addMethod(newMethod);
}
proxy.addInterface(intfClass);
}
return proxy;