/* */ package org.jboss.aop.proxy.container;
/* */
/* */ import java.lang.reflect.Method;
/* */ import java.security.ProtectionDomain;
/* */ import java.util.ArrayList;
/* */ import java.util.Collection;
/* */ import java.util.HashMap;
/* */ import java.util.HashSet;
/* */ import java.util.Iterator;
/* */ import java.util.Map;
/* */ import java.util.Map.Entry;
/* */ import java.util.Set;
/* */ import java.util.WeakHashMap;
/* */ import javassist.CannotCompileException;
/* */ import javassist.ClassPool;
/* */ import javassist.CtClass;
/* */ import javassist.CtConstructor;
/* */ import javassist.CtField;
/* */ import javassist.CtMethod;
/* */ import javassist.CtNewConstructor;
/* */ import javassist.CtNewMethod;
/* */ import javassist.Modifier;
/* */ import javassist.NotFoundException;
/* */ import javassist.SerialVersionUID;
/* */ import javassist.bytecode.AnnotationsAttribute;
/* */ import javassist.bytecode.ClassFile;
/* */ import javassist.bytecode.ParameterAnnotationsAttribute;
/* */ import javassist.bytecode.SignatureAttribute;
/* */ import javassist.bytecode.annotation.Annotation;
/* */ import org.jboss.aop.Advised;
/* */ import org.jboss.aop.Advisor;
/* */ import org.jboss.aop.AspectManager;
/* */ import org.jboss.aop.ClassContainer;
/* */ import org.jboss.aop.InstanceAdvised;
/* */ import org.jboss.aop.instrument.TransformerCommon;
/* */ import org.jboss.aop.introduction.InterfaceIntroduction;
/* */ import org.jboss.aop.introduction.InterfaceIntroduction.Mixin;
/* */ import org.jboss.aop.util.JavassistMethodHashing;
/* */
/* */ public class ContainerProxyFactory
/* */ {
/* 68 */ private static final String ADVISED = Advised.class.getName();
/* 69 */ private static final String INSTANCE_ADVISED = InstanceAdvised.class.getName();
/* 70 */ private static final CtClass[] EMPTY_CTCLASS_ARRAY = new CtClass[0];
/* */ public static final String PROXY_NAME_PREFIX = "AOPContainerProxy$";
/* 73 */ private static Object maplock = new Object();
/* 74 */ private static WeakHashMap proxyCache = new WeakHashMap();
/* 75 */ private static volatile int counter = 0;
/* */ private static CtMethod setDelegateMethod;
/* */ private boolean objectAsSuper;
/* */ private Advisor advisor;
/* */ private Class clazz;
/* */ private CtClass proxy;
/* */ private ClassPool pool;
/* */ private ArrayList mixins;
/* */ private boolean isAdvised;
/* */ private CtConstructor defaultCtor;
/* */
/* */ public static Class getProxyClass(Class clazz, AspectManager manager)
/* */ throws Exception
/* */ {
/* 105 */ ContainerProxyCacheKey key = new ContainerProxyCacheKey(clazz);
/* 106 */ ClassContainer container = getTempClassContainer(clazz, manager);
/* 107 */ return getProxyClass(false, key, container);
/* */ }
/* */
/* */ public static Class getProxyClass(boolean objectAsSuper, ContainerProxyCacheKey key, Advisor advisor)
/* */ throws Exception
/* */ {
/* 113 */ Class clazz = key.getClazz();
/* */
/* 115 */ if (Delegate.class.isAssignableFrom(clazz)) clazz = clazz.getSuperclass();
/* */
/* 117 */ Class proxyClass = null;
/* 118 */ synchronized (maplock)
/* */ {
/* 120 */ Map map = (Map)proxyCache.get(clazz);
/* 121 */ if (map == null)
/* */ {
/* 123 */ map = new HashMap();
/* 124 */ proxyCache.put(clazz, map);
/* */ }
/* */ else
/* */ {
/* 128 */ proxyClass = (Class)map.get(key);
/* */ }
/* */
/* 131 */ if (proxyClass == null)
/* */ {
/* 133 */ proxyClass = generateProxy(objectAsSuper, clazz, advisor);
/* 134 */ map.put(key, proxyClass);
/* */ }
/* */ }
/* 137 */ return proxyClass;
/* */ }
/* */
/* */ private static Class generateProxy(boolean objectAsSuper, Class clazz, Advisor advisor) throws Exception
/* */ {
/* 142 */ ArrayList introductions = advisor.getInterfaceIntroductions();
/* 143 */ CtClass proxy = createProxyCtClass(objectAsSuper, introductions, clazz, advisor);
/* 144 */ ProtectionDomain pd = clazz.getProtectionDomain();
/* 145 */ Class proxyClass = TransformerCommon.toClass(proxy, pd);
/* 146 */ return proxyClass;
/* */ }
/* */
/* */ private static ClassProxyContainer getTempClassContainer(Class clazz, AspectManager manager)
/* */ {
/* 151 */ ClassProxyContainer container = new ClassProxyContainer("temp", manager);
/* 152 */ container.setClass(clazz);
/* */
/* 154 */ Iterator it = container.getManager().getInterfaceIntroductions().values().iterator();
/* 155 */ while (it.hasNext())
/* */ {
/* 157 */ InterfaceIntroduction intro = (InterfaceIntroduction)it.next();
/* 158 */ if (intro.matches(container, container.getClazz()))
/* */ {
/* 160 */ container.addInterfaceIntroduction(intro);
/* */ }
/* */ }
/* */
/* 164 */ return container;
/* */ }
/* */
/* */ public static CtClass createProxyCtClass(boolean objectAsSuper, ArrayList mixins, Class clazz, Advisor advisor)
/* */ throws Exception
/* */ {
/* 170 */ ContainerProxyFactory factory = new ContainerProxyFactory(objectAsSuper, mixins, clazz, advisor);
/* 171 */ return factory.createProxyCtClass();
/* */ }
/* */
/* */ private ContainerProxyFactory(boolean objectAsSuper, ArrayList mixins, Class clazz, Advisor advisor)
/* */ {
/* 177 */ this.objectAsSuper = objectAsSuper;
/* 178 */ this.mixins = mixins;
/* 179 */ this.clazz = clazz;
/* 180 */ this.advisor = advisor;
/* 181 */ this.isAdvised = Advised.class.isAssignableFrom(clazz);
/* */ }
/* */
/* */ private CtClass createProxyCtClass()
/* */ throws Exception
/* */ {
/* 187 */ this.pool = AspectManager.instance().findClassPool(this.clazz.getClassLoader());
/* 188 */ if (this.pool == null) throw new NullPointerException("Could not find ClassPool");
/* */
/* 190 */ createBasics();
/* 191 */ addMethodsAndMixins();
/* 192 */ overrideSpecialMethods(this.clazz, this.proxy);
/* */
/* 194 */ SerialVersionUID.setSerialVersionUID(this.proxy);
/* */
/* 196 */ return this.proxy;
/* */ }
/* */
/* */ private CtClass createBasics()
/* */ throws Exception
/* */ {
/* 202 */ Class proxySuper = this.objectAsSuper ? Object.class : this.clazz;
/* 203 */ String classname = getClassName();
/* */
/* 205 */ CtClass template = this.pool.get("org.jboss.aop.proxy.container.ProxyTemplate");
/* 206 */ CtClass superclass = this.pool.get(proxySuper.getName());
/* */
/* 208 */ this.proxy = TransformerCommon.makeClass(this.pool, classname, superclass);
/* 209 */ this.proxy.addInterface(this.pool.get("org.jboss.aop.instrument.Untransformable"));
/* */
/* 212 */ Class[] interfaces = proxySuper.getInterfaces();
/* 213 */ for (int i = 0; i < interfaces.length; i++)
/* */ {
/* 215 */ CtClass interfaze = this.pool.get(interfaces[i].getName());
/* 216 */ this.proxy.addInterface(interfaze);
/* */ }
/* */
/* 219 */ copyConstructors(superclass, this.proxy);
/* 220 */ addFieldFromTemplate(template, "mixins");
/* */
/* 223 */ this.proxy.addInterface(this.pool.get("org.jboss.aop.proxy.container.Delegate"));
/* */
/* 225 */ addFieldFromTemplate(template, "delegate", superclass);
/* 226 */ addMethodFromTemplate(template, "getDelegate", "{ return delegate; }");
/* 227 */ setDelegateMethod = addMethodFromTemplate(template, "setDelegate", "{ this.delegate = (" + proxySuper.getName() + ")$1; }");
/* */
/* 230 */ this.proxy.addInterface(this.pool.get("org.jboss.aop.proxy.container.AspectManaged"));
/* */
/* 232 */ addFieldFromTemplate(template, "currentAdvisor");
/* 233 */ addFieldFromTemplate(template, "classAdvisor");
/* 234 */ addMethodFromTemplate(template, "getAdvisor", "{return classAdvisor;}");
/* 235 */ addMethodFromTemplate(template, "setAdvisor", "{this.classAdvisor = $1;currentAdvisor = classAdvisor;}");
/* */
/* 237 */ addFieldFromTemplate(template, "metadata");
/* 238 */ addMethodFromTemplate(template, "setMetadata", "{this.metadata = $1;}");
/* */
/* 240 */ addFieldFromTemplate(template, "instanceAdvisor");
/* 241 */ addMethodFromTemplate(template, "setInstanceAdvisor", instanceAdvisorSetterBody());
/* 242 */ addMethodFromTemplate(template, "getInstanceAdvisor", instanceAdvisorGetterBody());
/* */
/* 244 */ addMethodFromTemplate(template, "writeObject", writeObjectBody());
/* 245 */ addMethodFromTemplate(template, "readObject", readObjectBody(superclass));
/* */
/* 247 */ if (this.objectAsSuper)
/* */ {
/* 249 */ addMethodFromTemplate(template, "equals", equalsBody());
/* 250 */ addMethodFromTemplate(template, "hashCode", hashCodeBody());
/* */ }
/* */
/* 253 */ addMethodFromTemplate(template, "toString", toStringBody());
/* */
/* 255 */ copyAnnotations(superclass, this.proxy);
/* 256 */ copySignature(superclass, this.proxy);
/* */
/* 258 */ return this.proxy;
/* */ }
/* */
/* */ private String instanceAdvisorSetterBody()
/* */ {
/* 263 */ return "{ synchronized (this) { if (this.instanceAdvisor != null) { throw new RuntimeException(\"InstanceAdvisor already set\"); } if (!($1 instanceof org.jboss.aop.proxy.container.InstanceProxyContainer)) { throw new RuntimeException(\"Wrong type for instance advisor: \" + $1); } this.instanceAdvisor = $1; currentAdvisor = (org.jboss.aop.proxy.container.InstanceProxyContainer)$1; }}";
/* */ }
/* */
/* */ private String instanceAdvisorGetterBody()
/* */ {
/* 283 */ return "{ synchronized(this) { if (instanceAdvisor == null) { org.jboss.aop.proxy.container.InstanceProxyContainer ipc = ((org.jboss.aop.proxy.container.ClassProxyContainer)currentAdvisor).createInstanceProxyContainer(); setInstanceAdvisor(ipc); } } return instanceAdvisor;}";
/* */ }
/* */
/* */ private String writeObjectBody()
/* */ {
/* 299 */ return "{ $1.writeObject(delegate); $1.writeObject(mixins); $1.writeObject(metadata); $1.writeObject(classAdvisor.getClazz());}";
/* */ }
/* */
/* */ private String readObjectBody(CtClass superclass)
/* */ {
/* 311 */ return "{ delegate = (" + superclass.getName() + ")$1.readObject();" + " mixins = (Object[])$1.readObject();" + " metadata = (org.jboss.aop.metadata.SimpleMetaData)$1.readObject();" + " java.lang.Class clazz = (java.lang.Class)$1.readObject();" + " org.jboss.aop.AspectManager manager = org.jboss.aop.AspectManager.getTopLevelAspectManager();" + " classAdvisor = manager.findAdvisor(clazz);" + " currentAdvisor = classAdvisor;" + "}";
/* */ }
/* */
/* */ private String equalsBody()
/* */ {
/* 326 */ return "{ if (delegate != null) { if ($1 != null && $1 instanceof org.jboss.aop.proxy.container.Delegate) $1 = ((org.jboss.aop.proxy.container.Delegate) $1).getDelegate(); return delegate.equals($1); } else return super.equals($1);}";
/* */ }
/* */
/* */ private String hashCodeBody()
/* */ {
/* 341 */ return "{ if (delegate != null) return delegate.hashCode(); else return super.hashCode();}";
/* */ }
/* */
/* */ private String toStringBody()
/* */ {
/* 352 */ return "{ if (delegate != null) return delegate.toString() + \" (proxied by \" + this.getClass().getName() + \"@\" + java.lang.Integer.toHexString(java.lang.System.identityHashCode(this)) + \")\"; else return super.toString() + \" (empty proxy of \" + this.getClass().getSuperclass().getName() + \")\";}";
/* */ }
/* */
/* */ private CtField addFieldFromTemplate(CtClass template, String name)
/* */ throws Exception
/* */ {
/* 363 */ return addFieldFromTemplate(template, name, null);
/* */ }
/* */
/* */ private CtField addFieldFromTemplate(CtClass template, String name, CtClass type) throws Exception
/* */ {
/* 368 */ CtField templateField = template.getField(name);
/* 369 */ CtClass fieldType = type == null ? templateField.getType() : type;
/* 370 */ CtField field = new CtField(fieldType, name, this.proxy);
/* 371 */ field.setModifiers(templateField.getModifiers());
/* 372 */ this.proxy.addField(field);
/* 373 */ return field;
/* */ }
/* */
/* */ private CtMethod addMethodFromTemplate(CtClass template, String name, String body) throws Exception
/* */ {
/* 378 */ CtMethod templateMethod = template.getDeclaredMethod(name);
/* 379 */ CtMethod method = CtNewMethod.make(templateMethod.getReturnType(), name, templateMethod.getParameterTypes(), templateMethod.getExceptionTypes(), body, this.proxy);
/* 380 */ method.setModifiers(templateMethod.getModifiers());
/* 381 */ this.proxy.addMethod(method);
/* 382 */ return method;
/* */ }
/* */
/* */ private void copyConstructors(CtClass superclass, CtClass proxy) throws Exception
/* */ {
/* 387 */ CtConstructor[] ctors = superclass.getConstructors();
/* 388 */ int minParameters = 2147483647;
/* 389 */ CtConstructor bestCtor = null;
/* 390 */ for (int i = 0; i < ctors.length; i++)
/* */ {
/* 392 */ CtClass[] params = ctors[i].getParameterTypes();
/* */
/* 394 */ CtConstructor ctor = CtNewConstructor.make(ctors[i].getParameterTypes(), ctors[i].getExceptionTypes(), 2, null, null, proxy);
/* */
/* 401 */ ctor.setModifiers(ctors[i].getModifiers());
/* 402 */ proxy.addConstructor(ctor);
/* */
/* 404 */ if (params.length < minParameters)
/* */ {
/* 406 */ bestCtor = ctor;
/* 407 */ minParameters = params.length;
/* */ }
/* 409 */ if (params.length != 0)
/* */ continue;
/* 411 */ this.defaultCtor = ctor;
/* */ }
/* */
/* 415 */ if (minParameters > 0)
/* */ {
/* 418 */ createDefaultConstructor(bestCtor);
/* */ }
/* */ }
/* */
/* */ private void createDefaultConstructor(CtConstructor bestCtor) throws NotFoundException, CannotCompileException
/* */ {
/* 424 */ CtClass[] params = bestCtor.getParameterTypes();
/* */
/* 426 */ StringBuffer superCall = new StringBuffer("super(");
/* */
/* 428 */ for (int i = 0; i < params.length; i++)
/* */ {
/* 430 */ if (i > 0)
/* */ {
/* 432 */ superCall.append(", ");
/* */ }
/* */
/* 435 */ superCall.append(getNullType(params[i]));
/* */ }
/* */
/* 438 */ superCall.append(");");
/* */
/* 440 */ this.defaultCtor = CtNewConstructor.make(EMPTY_CTCLASS_ARRAY, EMPTY_CTCLASS_ARRAY, "{" + superCall.toString() + "}", this.proxy);
/* 441 */ this.proxy.addConstructor(this.defaultCtor);
/* */ }
/* */
/* */ private String getNullType(CtClass clazz)
/* */ {
/* 446 */ if (!clazz.isPrimitive())
/* */ {
/* 448 */ return "null";
/* */ }
/* */
/* 452 */ if (clazz.equals(CtClass.booleanType)) return "false";
/* 453 */ if (clazz.equals(CtClass.charType)) return "'0'";
/* 454 */ if (clazz.equals(CtClass.byteType)) return "0";
/* 455 */ if (clazz.equals(CtClass.shortType)) return "0";
/* 456 */ if (clazz.equals(CtClass.intType)) return "0";
/* 457 */ if (clazz.equals(CtClass.longType)) return "0L";
/* 458 */ if (clazz.equals(CtClass.floatType)) return "0f";
/* 459 */ if (clazz.equals(CtClass.doubleType)) return "0d";
/* 460 */ return "";
/* */ }
/* */
/* */ private void addMethodsAndMixins()
/* */ throws Exception
/* */ {
/* 467 */ HashSet addedMethods = new HashSet();
/* 468 */ createMixinsAndIntroductions(addedMethods);
/* 469 */ createProxyMethods(addedMethods);
/* */ }
/* */
/* */ private void createMixinsAndIntroductions(HashSet addedMethods) throws Exception
/* */ {
/* 474 */ HashSet addedInterfaces = new HashSet();
/* 475 */ Set implementedInterfaces = interfacesAsSet();
/* */
/* 477 */ if (this.mixins != null)
/* */ {
/* 479 */ HashMap intfs = new HashMap();
/* 480 */ HashMap mixinIntfs = new HashMap();
/* 481 */ ArrayList mixes = new ArrayList();
/* 482 */ for (int i = 0; i < this.mixins.size(); i++)
/* */ {
/* 484 */ InterfaceIntroduction introduction = (InterfaceIntroduction)this.mixins.get(i);
/* 485 */ getIntroductionInterfaces(introduction, intfs, mixinIntfs, mixes, i);
/* */ }
/* 487 */ if (mixes.size() > 0)
/* */ {
/* 489 */ this.defaultCtor.insertAfter("mixins = new Object[" + mixes.size() + "];");
/* 490 */ for (int i = 0; i < mixes.size(); i++)
/* */ {
/* 494 */ InterfaceIntroduction.Mixin mixin = (InterfaceIntroduction.Mixin)mixes.get(i);
/* 495 */ String initializer = mixin.getConstruction() == null ? "new " + mixin.getClassName() + "()" : mixin.getConstruction();
/* 496 */ String code = "mixins[" + i + "] = " + initializer + ";";
/* 497 */ this.defaultCtor.insertAfter(code);
/* 498 */ setDelegateMethod.insertAfter("{if (org.jboss.aop.proxy.container.Delegate.class.isAssignableFrom(mixins[" + i + "].getClass())) " + "((org.jboss.aop.proxy.container.Delegate)mixins[" + i + "]).setDelegate($1);}");
/* */ }
/* */
/* */ }
/* */
/* 504 */ HashMap allMethods = JavassistMethodHashing.getDeclaredMethodMap(this.proxy);
/* 505 */ addedMethods.addAll(allMethods.keySet());
/* */
/* 507 */ createMixins(addedMethods, mixes, addedInterfaces, implementedInterfaces);
/* 508 */ createIntroductions(addedMethods, intfs, addedInterfaces, implementedInterfaces);
/* */ }
/* */ }
/* */
/* */ private void getIntroductionInterfaces(InterfaceIntroduction intro, HashMap intfs, HashMap mixins, ArrayList mixes, int idx)
/* */ {
/* 523 */ Iterator it = intro.getMixins().iterator();
/* 524 */ while (it.hasNext())
/* */ {
/* 526 */ InterfaceIntroduction.Mixin mixin = (InterfaceIntroduction.Mixin)it.next();
/* 527 */ mixes.add(mixin);
/* 528 */ for (int i = 0; i < mixin.getInterfaces().length; i++)
/* */ {
/* 530 */ if (intfs.containsKey(mixin.getInterfaces()[i]))
/* */ {
/* 532 */ intfs.remove(mixin.getInterfaces()[i]);
/* */ }
/* */
/* 535 */ if (mixins.containsKey(mixin.getInterfaces()[i]))
/* */ {
/* 537 */ throw new RuntimeException("cannot have an IntroductionInterface that introduces several mixins with the same interfaces " + mixin.getInterfaces()[i]);
/* */ }
/* 539 */ mixins.put(mixin.getInterfaces()[i], new Integer(idx));
/* */ }
/* */ }
/* 542 */ if (intro.getInterfaces() != null)
/* */ {
/* 544 */ for (int i = 0; i < intro.getInterfaces().length; i++)
/* */ {
/* 546 */ if ((intfs.containsKey(intro.getInterfaces()[i])) || (mixins.containsKey(intro.getInterfaces()[i])))
/* */ {
/* */ continue;
/* */ }
/* */
/* 552 */ intfs.put(intro.getInterfaces()[i], new Integer(idx));
/* */ }
/* */ }
/* */ }
/* */
/* */ private void createMixins(HashSet addedMethods, ArrayList mixes, HashSet addedInterfaces, Set implementedInterfaces)
/* */ throws Exception
/* */ {
/* 560 */ for (int mixinId = 0; mixinId < mixes.size(); mixinId++)
/* */ {
/* 562 */ InterfaceIntroduction.Mixin mixin = (InterfaceIntroduction.Mixin)mixes.get(mixinId);
/* */
/* 564 */ String[] intfs = mixin.getInterfaces();
/* */
/* 566 */ for (int ifId = 0; ifId < intfs.length; ifId++)
/* */ {
/* 568 */ String intf = intfs[ifId];
/* 569 */ if (addedInterfaces.contains(intf)) throw new Exception("2 mixins are implementing the same interfaces " + intf);
/* 570 */ if (implementedInterfaces.contains(intf)) throw new Exception("Attempting to mixin interface already used by class " + intf);
/* */
/* 572 */ CtClass intfClass = this.pool.get(intf);
/* 573 */ CtMethod[] methods = intfClass.getMethods();
/* 574 */ HashSet mixinMethods = new HashSet();
/* 575 */ for (int m = 0; m < methods.length; m++)
/* */ {
/* 577 */ if (!methods[m].getDeclaringClass().getName().equals("java.lang.Object")) {
/* 578 */ Long hash = new Long(JavassistMethodHashing.methodHash(methods[m]));
/* 579 */ if (!mixinMethods.contains(hash)) {
/* 580 */ if (addedMethods.contains(hash)) throw new Exception("More than one mixin has same method");
/* 581 */ mixinMethods.add(hash);
/* 582 */ addedMethods.add(hash);
/* 583 */ String aopReturnStr = methods[m].getReturnType().equals(CtClass.voidType) ? "" : "return ($r)";
/* 584 */ String returnStr = methods[m].getReturnType().equals(CtClass.voidType) ? "" : "return ";
/* 585 */ String args = "null";
/* 586 */ if (methods[m].getParameterTypes().length > 0) args = "$args";
/* 587 */ String code = "{ try{ " + intf + " mixin = (" + intf + ")mixins[" + mixinId + "];" + " org.jboss.aop.MethodInfo mi = currentAdvisor.getMethodInfo(" + hash.longValue() + "L); " + " org.jboss.aop.advice.Interceptor[] interceptors = mi.getInterceptors();" + " if (mi != null && interceptors != (Object[])null && interceptors.length > 0) { " + " org.jboss.aop.proxy.container.ContainerProxyMethodInvocation invocation = new org.jboss.aop.proxy.container.ContainerProxyMethodInvocation(mi, interceptors, this); " + " invocation.setArguments(" + args + "); " + " invocation.setTargetObject(mixin); " + " invocation.setMetaData(metadata);" + " " + aopReturnStr + " invocation.invokeNext(); " + " } else { " + " " + returnStr + " mixin." + methods[m].getName() + "($$);" + " } " + " }finally{" + " }" + "}";
/* */
/* 604 */ CtMethod newMethod = CtNewMethod.make(methods[m].getReturnType(), methods[m].getName(), methods[m].getParameterTypes(), methods[m].getExceptionTypes(), code, this.proxy);
/* 605 */ newMethod.setModifiers(1);
/* 606 */ this.proxy.addMethod(newMethod);
/* */
/* 608 */ copySignature(methods[m], newMethod);
/* */ }
/* */ }
/* */ }
/* 611 */ this.proxy.addInterface(intfClass);
/* 612 */ addedInterfaces.add(intfClass.getName());
/* */ }
/* */ }
/* */ }
/* */
/* */ private void createProxyMethods(HashSet addedMethods) throws Exception
/* */ {
/* 619 */ HashMap allMethods = JavassistMethodHashing.getMethodMap(this.proxy.getSuperclass());
/* */
/* 621 */ Iterator it = allMethods.entrySet().iterator();
/* 622 */ while (it.hasNext())
/* */ {
/* 624 */ Map.Entry entry = (Map.Entry)it.next();
/* 625 */ CtMethod m = (CtMethod)entry.getValue();
/* 626 */ if ((!Modifier.isPublic(m.getModifiers())) || (Modifier.isStatic(m.getModifiers())) || (Modifier.isFinal(m.getModifiers())))
/* */ continue;
/* 628 */ Long hash = (Long)entry.getKey();
/* 629 */ if (!addedMethods.contains(hash)) {
/* 630 */ addedMethods.add(hash);
/* 631 */ String aopReturnStr = m.getReturnType().equals(CtClass.voidType) ? "" : "return ($r)";
/* 632 */ String returnStr = m.getReturnType().equals(CtClass.voidType) ? "" : "return ";
/* 633 */ String args = "null";
/* */
/* 635 */ String name = null;
/* 636 */ if (this.isAdvised)
/* */ {
/* 638 */ org.jboss.aop.MethodInfo info = this.advisor.getMethodInfo(hash.longValue());
/* 639 */ Method originalMethod = info.getUnadvisedMethod();
/* 640 */ name = originalMethod.getName();
/* */ }
/* */ else
/* */ {
/* 644 */ name = m.getName();
/* */ }
/* */
/* 647 */ if (m.getParameterTypes().length > 0) args = "$args";
/* 648 */ String code = "{ boolean handled = false; try{ if (currentAdvisor != null) { org.jboss.aop.MethodInfo mi = currentAdvisor.getMethodInfo(" + hash.longValue() + "L); " + " if (mi == null) " + " throw new java.lang.NoSuchMethodError(\"" + m.getName() + m.getSignature() + "\");" + " org.jboss.aop.advice.Interceptor[] interceptors = mi.getInterceptors(); " + " if (interceptors != (Object[])null && interceptors.length > 0) { " + " handled = true;" + " org.jboss.aop.proxy.container.ContainerProxyMethodInvocation invocation = new org.jboss.aop.proxy.container.ContainerProxyMethodInvocation(mi, interceptors, this); " + " invocation.setArguments(" + args + "); " + " invocation.setTargetObject(delegate); " + " invocation.setMetaData(metadata);" + " " + aopReturnStr + " invocation.invokeNext(); " + " }" + " }" + " if (!handled && delegate != null){ " + " " + returnStr + " delegate." + name + "($$); " + " }" + " return " + getNullType(m.getReturnType()) + ";" + " }finally{" + " }" + "}";
/* */
/* 672 */ CtMethod newMethod = CtNewMethod.make(m.getReturnType(), m.getName(), m.getParameterTypes(), m.getExceptionTypes(), code, this.proxy);
/* 673 */ newMethod.setModifiers(1);
/* 674 */ this.proxy.addMethod(newMethod);
/* */
/* 676 */ copyAnnotations(m, newMethod);
/* 677 */ copySignature(m, newMethod);
/* */ }
/* */ }
/* */ }
/* */
/* */ private void createIntroductions(HashSet addedMethods, HashMap intfs, HashSet addedInterfaces, Set implementedInterfaces) throws Exception {
/* 683 */ Iterator it = intfs.keySet().iterator();
/* 684 */ while (it.hasNext())
/* */ {
/* 686 */ String intf = (String)it.next();
/* 687 */ if (addedInterfaces.contains(intf)) throw new Exception("2 mixins are implementing the same interfaces");
/* 688 */ if (implementedInterfaces.contains(intf))
/* */ {
/* */ continue;
/* */ }
/* */
/* 693 */ CtClass intfClass = this.pool.get(intf);
/* 694 */ CtMethod[] methods = intfClass.getMethods();
/* 695 */ HashSet mixinMethods = new HashSet();
/* 696 */ for (int m = 0; m < methods.length; m++)
/* */ {
/* 698 */ if (methods[m].getDeclaringClass().getName().equals("java.lang.Object"))
/* */ continue;
/* 700 */ Long hash = new Long(JavassistMethodHashing.methodHash(methods[m]));
/* 701 */ if ((mixinMethods.contains(hash)) ||
/* 702 */ (addedMethods.contains(hash)))
/* */ continue;
/* 704 */ mixinMethods.add(hash);
/* 705 */ addedMethods.add(hash);
/* 706 */ String aopReturnStr = methods[m].getReturnType().equals(CtClass.voidType) ? "" : "return ($r)";
/* 707 */ String args = "null";
/* 708 */ if (methods[m].getParameterTypes().length > 0) args = "$args";
/* 709 */ String code = "{ try{ org.jboss.aop.MethodInfo mi = currentAdvisor.getMethodInfo(" + hash.longValue() + "L); " + " if (mi == null) " + " throw new java.lang.NoSuchMethodError(\"" + methods[m].getName() + methods[m].getSignature() + "\");" + " org.jboss.aop.advice.Interceptor[] interceptors = mi.getInterceptors();" + " org.jboss.aop.proxy.container.ContainerProxyMethodInvocation invocation = new org.jboss.aop.proxy.container.ContainerProxyMethodInvocation(mi, interceptors, this); " + " invocation.setArguments(" + args + "); " + " invocation.setTargetObject(delegate); " + " invocation.setMetaData(metadata);" + " " + aopReturnStr + " invocation.invokeNext(); " + " }finally{" + " }" + "}";
/* */
/* 724 */ CtMethod newMethod = CtNewMethod.make(methods[m].getReturnType(), methods[m].getName(), methods[m].getParameterTypes(), methods[m].getExceptionTypes(), code, this.proxy);
/* 725 */ newMethod.setModifiers(1);
/* 726 */ this.proxy.addMethod(newMethod);
/* */
/* 728 */ copySignature(methods[m], newMethod);
/* */ }
/* */
/* 731 */ this.proxy.addInterface(intfClass);
/* 732 */ addedInterfaces.add(intfClass.getName());
/* */ }
/* */ }
/* */
/* */ private Set interfacesAsSet() throws NotFoundException
/* */ {
/* 738 */ HashSet set = new HashSet();
/* 739 */ CtClass[] interfaces = this.proxy.getInterfaces();
/* */
/* 741 */ for (int i = 0; i < interfaces.length; i++)
/* */ {
/* 743 */ set.add(interfaces[i].getName());
/* */ }
/* */
/* 746 */ return set;
/* */ }
/* */
/* */ private String getClassName()
/* */ {
/* 751 */ String packageName = this.clazz.getPackage().getName();
/* 752 */ if ((!packageName.startsWith("java.")) && (!packageName.startsWith("sun.")))
/* */ {
/* 754 */ packageName = packageName + ".";
/* */ }
/* */ else
/* */ {
/* 758 */ packageName = "";
/* */ }
/* */
/* 761 */ return packageName + "AOPContainerProxy$" + counter++;
/* */ }
/* */
/* */ private void overrideSpecialMethods(Class clazz, CtClass proxy) throws Exception
/* */ {
/* 766 */ addInstanceAdvisedMethods(clazz, proxy);
/* */ }
/* */
/* */ private void addInstanceAdvisedMethods(Class clazz, CtClass proxy)
/* */ throws Exception
/* */ {
/* 775 */ CtClass advisedInterface = null;
/* 776 */ CtClass[] interfaces = proxy.getInterfaces();
/* */
/* 778 */ for (int i = 0; i < interfaces.length; i++)
/* */ {
/* 780 */ if (!interfaces[i].getName().equals(ADVISED))
/* */ continue;
/* 782 */ advisedInterface = interfaces[i];
/* 783 */ break;
/* */ }
/* */
/* 787 */ if (advisedInterface != null)
/* */ {
/* 789 */ CtMethod[] methods = advisedInterface.getMethods();
/* 790 */ for (int i = 0; i < methods.length; i++)
/* */ {
/* 792 */ if (!methods[i].getDeclaringClass().getName().equals(INSTANCE_ADVISED))
/* */ continue;
/* 794 */ String name = methods[i].getName();
/* 795 */ String body = null;
/* 796 */ if (name.equals("_getInstanceAdvisor"))
/* */ {
/* 798 */ body = "{ return getInstanceAdvisor(); }";
/* */ }
/* 800 */ else if (name.equals("_setInstanceAdvisor"))
/* */ {
/* 802 */ body = "{ setInstanceAdvisor($1); }";
/* */ }
/* */
/* 805 */ if (body == null)
/* */ continue;
/* 807 */ CtMethod m = CtNewMethod.make(methods[i].getReturnType(), methods[i].getName(), methods[i].getParameterTypes(), methods[i].getExceptionTypes(), body, proxy);
/* 808 */ m.setModifiers(1);
/* 809 */ proxy.addMethod(m);
/* */ }
/* */ }
/* */ }
/* */
/* */ private void copyAnnotations(CtMethod src, CtMethod dest)
/* */ throws NotFoundException
/* */ {
/* 818 */ javassist.bytecode.MethodInfo srcInfo = src.getMethodInfo2();
/* 819 */ javassist.bytecode.MethodInfo destInfo = dest.getMethodInfo2();
/* 820 */ copyAnnotations(srcInfo, destInfo, "RuntimeInvisibleAnnotations");
/* 821 */ copyAnnotations(srcInfo, destInfo, "RuntimeVisibleAnnotations");
/* */
/* 823 */ int numParams = src.getParameterTypes().length;
/* 824 */ copyParameterAnnotations(numParams, srcInfo, destInfo, "RuntimeVisibleParameterAnnotations");
/* 825 */ copyParameterAnnotations(numParams, srcInfo, destInfo, "RuntimeInvisibleParameterAnnotations");
/* */ }
/* */
/* */ private void copyAnnotations(javassist.bytecode.MethodInfo src, javassist.bytecode.MethodInfo dest, String annotationTag)
/* */ {
/* 831 */ AnnotationsAttribute attribute = (AnnotationsAttribute)src.getAttribute(annotationTag);
/* 832 */ if (attribute != null)
/* */ {
/* 834 */ dest.addAttribute(attribute.copy(dest.getConstPool(), new HashMap()));
/* */ }
/* */ }
/* */
/* */ private void copyParameterAnnotations(int numParams, javassist.bytecode.MethodInfo src, javassist.bytecode.MethodInfo dest, String paramsTag)
/* */ {
/* 840 */ ParameterAnnotationsAttribute params = (ParameterAnnotationsAttribute)src.getAttribute(paramsTag);
/* 841 */ if (params != null)
/* */ {
/* 843 */ dest.addAttribute(params.copy(dest.getConstPool(), new HashMap()));
/* 844 */ ParameterAnnotationsAttribute srcParams = new ParameterAnnotationsAttribute(src.getConstPool(), paramsTag);
/* 845 */ Annotation[][] emptyParamAnnotations = new Annotation[numParams][];
/* 846 */ for (int i = 0; i < numParams; i++)
/* */ {
/* 848 */ emptyParamAnnotations[i] = new Annotation[0];
/* */ }
/* 850 */ srcParams.setAnnotations(emptyParamAnnotations);
/* 851 */ src.addAttribute(srcParams);
/* */ }
/* */ }
/* */
/* */ private void copyAnnotations(CtClass src, CtClass dest) throws NotFoundException
/* */ {
/* 857 */ ClassFile srcFile = src.getClassFile2();
/* 858 */ ClassFile destFile = dest.getClassFile2();
/* 859 */ copyAnnotations(srcFile, destFile, "RuntimeInvisibleAnnotations");
/* 860 */ copyAnnotations(srcFile, destFile, "RuntimeVisibleAnnotations");
/* */ }
/* */
/* */ private void copyAnnotations(ClassFile src, ClassFile dest, String annotationTag)
/* */ {
/* 865 */ AnnotationsAttribute attribute = (AnnotationsAttribute)src.getAttribute(annotationTag);
/* 866 */ if (attribute != null)
/* */ {
/* 868 */ dest.addAttribute(attribute.copy(dest.getConstPool(), new HashMap()));
/* */ }
/* */ }
/* */
/* */ private void copySignature(CtMethod src, CtMethod dest)
/* */ {
/* 875 */ javassist.bytecode.MethodInfo srcInfo = src.getMethodInfo2();
/* 876 */ javassist.bytecode.MethodInfo destInfo = dest.getMethodInfo2();
/* */
/* 878 */ SignatureAttribute sig = (SignatureAttribute)srcInfo.getAttribute("Signature");
/* 879 */ if (sig != null)
/* */ {
/* 881 */ destInfo.addAttribute(sig.copy(destInfo.getConstPool(), new HashMap()));
/* */ }
/* */ }
/* */
/* */ private void copySignature(CtClass src, CtClass dest)
/* */ {
/* 887 */ ClassFile srcFile = src.getClassFile2();
/* 888 */ ClassFile destFile = dest.getClassFile2();
/* */
/* 890 */ SignatureAttribute sig = (SignatureAttribute)srcFile.getAttribute("Signature");
/* 891 */ if (sig != null)
/* */ {
/* 893 */ destFile.addAttribute(sig.copy(destFile.getConstPool(), new HashMap()));
/* */ }
/* */ }
/* */ }
/* Location: /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/jboss-embedded-all.jar
* Qualified Name: org.jboss.aop.proxy.container.ContainerProxyFactory
* JD-Core Version: 0.6.0
*/