1 8 package org.codehaus.aspectwerkz.transform.inlining.weaver; 9 10 import org.objectweb.asm.ClassAdapter; 11 import org.objectweb.asm.Constants; 12 import org.objectweb.asm.ClassVisitor; 13 import org.objectweb.asm.CodeVisitor; 14 import org.objectweb.asm.Attribute; 15 import org.objectweb.asm.Type; 16 import org.objectweb.asm.CodeAdapter; 17 import org.objectweb.asm.Label; 18 import org.codehaus.aspectwerkz.reflect.ClassInfo; 19 import org.codehaus.aspectwerkz.reflect.ConstructorInfo; 20 import org.codehaus.aspectwerkz.transform.Context; 21 import org.codehaus.aspectwerkz.transform.TransformationUtil; 22 import org.codehaus.aspectwerkz.transform.TransformationConstants; 23 import org.codehaus.aspectwerkz.transform.inlining.ContextImpl; 24 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper; 25 import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint; 26 import org.codehaus.aspectwerkz.expression.ExpressionContext; 27 import org.codehaus.aspectwerkz.expression.PointcutType; 28 import org.codehaus.aspectwerkz.definition.SystemDefinition; 29 import org.codehaus.aspectwerkz.joinpoint.management.JoinPointType; 30 31 import java.util.Iterator ; 32 import java.util.Set ; 33 34 44 public class ConstructorBodyVisitor extends ClassAdapter implements TransformationConstants { 45 46 private final ContextImpl m_ctx; 47 private final ClassInfo m_calleeClassInfo; 48 private String m_declaringTypeName; 49 private Set m_addedMethods; 50 51 59 public ConstructorBodyVisitor(final ClassVisitor cv, 60 final ClassInfo classInfo, 61 final Context ctx, 62 final Set addedMethods) { 63 super(cv); 64 m_calleeClassInfo = classInfo; 65 m_ctx = (ContextImpl) ctx; 66 m_addedMethods = addedMethods; 67 } 68 69 78 public void visit(final int version, 79 final int access, 80 final String name, 81 final String superName, 82 final String [] interfaces, 83 final String sourceFile) { 84 m_declaringTypeName = name; 85 super.visit(version, access, name, superName, interfaces, sourceFile); 86 } 87 88 96 public CodeVisitor visitMethod(int access, 97 String name, 98 String desc, 99 String [] exceptions, 100 Attribute attrs) { 101 if (!INIT_METHOD_NAME.equals(name)) { 102 return super.visitMethod(access, name, desc, exceptions, attrs); 103 } 104 105 int hash = AsmHelper.calculateConstructorHash(desc); 106 ConstructorInfo constructorInfo = m_calleeClassInfo.getConstructor(hash); 107 if (constructorInfo == null) { 108 System.err.println( 109 "AW::WARNING " + 110 "metadata structure could not be build for constructor [" 111 + m_calleeClassInfo.getName().replace('/', '.') 112 + ".<init>: " + desc + ']' 113 ); 114 return cv.visitMethod(access, name, desc, exceptions, attrs); 115 } 116 117 ExpressionContext ctx = new ExpressionContext(PointcutType.EXECUTION, constructorInfo, constructorInfo); 118 119 if (constructorFilter(m_ctx.getDefinitions(), ctx)) { 120 return cv.visitMethod(access, name, desc, exceptions, attrs); 121 } else { 122 String wrapperName = TransformationUtil.getConstructorBodyMethodName(m_declaringTypeName); 123 String wrapperDesc = TransformationUtil.getConstructorBodyMethodSignature(desc, m_declaringTypeName); 124 if (m_addedMethods.contains(AlreadyAddedMethodAdapter.getMethodKey(wrapperName, wrapperDesc))) { 125 return cv.visitMethod(access, name, desc, exceptions, attrs); 126 } 127 128 m_ctx.markAsAdvised(); 129 130 CodeVisitor proxyCtorCodeVisitor = cv.visitMethod(access, name, desc, exceptions, attrs); 132 int modifiers = ACC_SYNTHETIC | ACC_STATIC; 134 CodeVisitor ctorBodyMethodCodeVisitor = cv.visitMethod( 135 modifiers, wrapperName, wrapperDesc, exceptions, attrs 136 ); 137 138 return new DispatchCtorBodyCodeAdapter(proxyCtorCodeVisitor, ctorBodyMethodCodeVisitor, access, desc); 140 } 141 } 142 143 144 151 private void insertJoinPointInvoke(final CodeVisitor ctorProxy, 152 final int access, 153 final String desc) { 154 ctorProxy.visitVarInsn(ALOAD, 0); AsmHelper.loadArgumentTypes(ctorProxy, Type.getArgumentTypes(desc), false); 158 159 ctorProxy.visitVarInsn(ALOAD, 0); 161 162 int joinPointHash = AsmHelper.calculateConstructorHash(desc); 163 String joinPointClassName = TransformationUtil.getJoinPointClassName( 164 m_declaringTypeName, 165 INIT_METHOD_NAME, 166 desc, 167 m_declaringTypeName, 168 JoinPointType.CONSTRUCTOR_EXECUTION_INT, 169 joinPointHash 170 ); 171 172 ctorProxy.visitMethodInsn( 173 INVOKESTATIC, 174 joinPointClassName, 175 INVOKE_METHOD_NAME, 176 TransformationUtil.getInvokeSignatureForCodeJoinPoints( 177 access, desc, m_declaringTypeName, m_declaringTypeName 178 ) 179 ); 180 181 m_ctx.addEmittedJoinPoint( 183 new EmittedJoinPoint( 184 JoinPointType.CONSTRUCTOR_EXECUTION_INT, 185 m_declaringTypeName, 186 TransformationConstants.INIT_METHOD_NAME, 187 desc, 188 access, 189 m_declaringTypeName, 190 TransformationConstants.INIT_METHOD_NAME, 191 desc, 192 access, 193 joinPointHash, 194 joinPointClassName, 195 EmittedJoinPoint.NO_LINE_NUMBER 196 ) 197 ); 198 } 199 200 207 public static boolean constructorFilter(final Set definitions, 208 final ExpressionContext ctx) { 209 for (Iterator it = definitions.iterator(); it.hasNext();) { 210 if (((SystemDefinition) it.next()).hasPointcut(ctx)) { 211 return false; 212 } else { 213 continue; 214 } 215 } 216 return true; 217 } 218 219 233 private class DispatchCtorBodyCodeAdapter extends CodeAdapter { 234 private CodeVisitor m_ctorBodyMethodCodeVisitor; 235 private CodeVisitor m_proxyCtorCodeVisitor; 236 private final int m_constructorAccess; 237 private final String m_constructorDesc; 238 239 private int m_newCount = 0; 240 241 private boolean m_proxyCtorCodeDone = false; 242 private boolean m_isALOADDUPHeuristic = false; 243 private int m_index = -1; 244 245 public DispatchCtorBodyCodeAdapter(CodeVisitor proxyCtor, CodeVisitor ctorBodyMethod, final int access, 246 final String desc) { 247 super(proxyCtor); 248 m_proxyCtorCodeVisitor = proxyCtor; 249 m_ctorBodyMethodCodeVisitor = ctorBodyMethod; 250 m_constructorAccess = access; 251 m_constructorDesc = desc; 252 } 253 254 public void visitInsn(int opcode) { 255 super.visitInsn(opcode); 256 if (!m_proxyCtorCodeDone && opcode == DUP && m_index == 0) { 257 m_isALOADDUPHeuristic = true; 259 m_index++; 260 } 261 } 262 263 public void visitIntInsn(int i, int i1) { 264 super.visitIntInsn(i, i1); 265 } 266 267 public void visitVarInsn(int opcode, int i1) { 268 super.visitVarInsn(opcode, i1); 269 if (!m_proxyCtorCodeDone) { 270 if (opcode == ALOAD && i1 == 0) { 271 m_index++; 272 } 273 } 274 } 275 276 public void visitFieldInsn(int i, String s, String s1, String s2) { 277 super.visitFieldInsn(i, s, s1, s2); 278 } 279 280 public void visitLdcInsn(Object o) { 281 super.visitLdcInsn(o); 282 } 283 284 public void visitIincInsn(int i, int i1) { 285 super.visitIincInsn(i, i1); 286 } 287 288 public void visitMultiANewArrayInsn(String s, int i) { 289 super.visitMultiANewArrayInsn(s, i); 290 } 291 292 298 public void visitTypeInsn(int opcode, String name) { 299 super.visitTypeInsn(opcode, name); 300 if (opcode == NEW) { 301 m_newCount++; 302 } 303 } 304 305 public void visitMethodInsn(int opcode, 306 String owner, 307 String name, 308 String desc) { 309 if (!m_proxyCtorCodeDone) { 310 if (opcode == INVOKESPECIAL) { 311 if (m_newCount == 0) { 312 m_proxyCtorCodeVisitor.visitMethodInsn(opcode, owner, name, desc); 314 insertJoinPointInvoke(m_proxyCtorCodeVisitor, m_constructorAccess, m_constructorDesc); 316 m_proxyCtorCodeVisitor.visitInsn(RETURN); 317 m_proxyCtorCodeVisitor.visitMaxs(0, 0); 318 m_proxyCtorCodeVisitor = null; 319 m_proxyCtorCodeDone = true; 320 cv = m_ctorBodyMethodCodeVisitor; 321 if (m_isALOADDUPHeuristic) { 323 m_ctorBodyMethodCodeVisitor.visitVarInsn(ALOAD, 0); 324 } 325 } else { 326 m_newCount--; 327 cv.visitMethodInsn(opcode, owner, name, desc); 328 } 329 } else { 330 cv.visitMethodInsn(opcode, owner, name, desc); 331 } 332 } else { 333 cv.visitMethodInsn(opcode, owner, name, desc); 334 } 335 } 336 337 } 338 } 339 | Popular Tags |