1 4 package com.tc.aspectwerkz.transform.inlining.weaver; 5 6 import com.tc.asm.ClassAdapter; 7 import com.tc.asm.ClassVisitor; 8 import com.tc.asm.MethodVisitor; 9 import com.tc.asm.MethodAdapter; 10 import com.tc.asm.Label; 11 import com.tc.asm.Type; 12 13 import com.tc.aspectwerkz.definition.SystemDefinition; 14 import com.tc.aspectwerkz.joinpoint.management.JoinPointType; 15 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo; 16 import com.tc.aspectwerkz.reflect.ClassInfo; 17 import com.tc.aspectwerkz.reflect.MemberInfo; 18 import com.tc.aspectwerkz.transform.InstrumentationContext; 19 import com.tc.aspectwerkz.transform.TransformationConstants; 20 import com.tc.aspectwerkz.transform.TransformationUtil; 21 import com.tc.aspectwerkz.transform.inlining.AsmHelper; 22 import com.tc.aspectwerkz.transform.inlining.EmittedJoinPoint; 23 import com.tc.aspectwerkz.expression.ExpressionContext; 24 import com.tc.aspectwerkz.expression.PointcutType; 25 26 import java.util.Iterator ; 27 import java.util.Set ; 28 import java.util.ArrayList ; 29 import java.util.List ; 30 import java.util.Map ; 31 import java.util.HashMap ; 32 import java.lang.reflect.Modifier ; 33 34 39 public class HandlerVisitor extends ClassAdapter implements TransformationConstants { 40 41 47 public static class LookaheadCatchLabelsClassAdapter extends ClassAdapter { 48 49 52 List m_catchLabels = new ArrayList (); 53 54 57 private final Map m_labelIndexes = new HashMap (); 58 59 62 private int m_labelIndex = -1; 63 64 private final InstrumentationContext m_ctx; 65 private final ClassLoader m_loader; 66 private final ClassInfo m_callerClassInfo; 67 68 77 public LookaheadCatchLabelsClassAdapter(ClassVisitor cv, ClassLoader loader, ClassInfo callerClassInfo, 78 InstrumentationContext ctx, List catchLabels) { 79 super(cv); 80 m_catchLabels = catchLabels; 81 m_loader = loader; 82 m_callerClassInfo = callerClassInfo; 83 m_ctx = (InstrumentationContext) ctx; 84 } 85 86 95 public MethodVisitor visitMethod(final int access, 96 final String callerMethodName, 97 final String callerMethodDesc, 98 final String callerMethodsignature, 99 final String [] exceptions) { 100 if (callerMethodName.startsWith(WRAPPER_METHOD_PREFIX)) { 101 return super.visitMethod(access, callerMethodName, callerMethodDesc, callerMethodsignature, exceptions); 102 } 103 104 MethodVisitor mv = cv.visitMethod(access, callerMethodName, callerMethodDesc, callerMethodsignature, exceptions); 105 if (mv == null) { 106 return mv; 107 } 108 109 final MemberInfo callerMemberInfo; 110 if (CLINIT_METHOD_NAME.equals(callerMethodName)) { 111 callerMemberInfo = m_callerClassInfo.staticInitializer(); 112 } else if (INIT_METHOD_NAME.equals(callerMethodName)) { 113 int hash = AsmHelper.calculateConstructorHash(callerMethodDesc); 114 callerMemberInfo = m_callerClassInfo.getConstructor(hash); 115 } else { 116 int hash = AsmHelper.calculateMethodHash(callerMethodName, callerMethodDesc); 117 callerMemberInfo = m_callerClassInfo.getMethod(hash); 118 } 119 if (callerMemberInfo == null) { 120 System.err.println( 121 "AW::WARNING " + 122 "metadata structure could not be build for method [" 123 + m_callerClassInfo.getName().replace('/', '.') 124 + '.' + callerMethodName + ':' + callerMethodDesc + ']' 125 ); 126 return mv; 127 } 128 129 return new LookaheadCatchLabelsMethodAdapter(mv, callerMemberInfo, this); 130 } 131 } 132 133 139 private static final class LookaheadCatchLabelsMethodAdapter extends MethodAdapter { 140 private final MemberInfo info; 141 private final LookaheadCatchLabelsClassAdapter classAdapter; 142 143 private LookaheadCatchLabelsMethodAdapter(MethodVisitor mv, MemberInfo info, LookaheadCatchLabelsClassAdapter classAdapter) { 144 super(mv); 145 this.info = info; 146 this.classAdapter = classAdapter; 147 } 148 149 public void visitLabel(Label label) { 150 classAdapter.m_labelIndexes.put(label, new Integer (++classAdapter.m_labelIndex)); 151 super.visitLabel(label); 152 } 153 154 public void visitTryCatchBlock(Label startLabel, Label endLabel, Label handlerLabel, 155 String exceptionTypeName) { 156 if (exceptionTypeName == null) { 157 super.visitTryCatchBlock(startLabel, endLabel, handlerLabel, exceptionTypeName); 159 return; 160 } 161 final ClassInfo exceptionClassInfo = AsmClassInfo.getClassInfo(exceptionTypeName, classAdapter.m_loader); 162 final ExpressionContext ctx = new ExpressionContext( 163 PointcutType.HANDLER, exceptionClassInfo, info 164 ); 165 if (!handlerFilter(classAdapter.m_ctx.getDefinitions(), ctx)) { 166 Integer index = (Integer ) classAdapter.m_labelIndexes.get(handlerLabel); 168 if (index != null) { 169 classAdapter.m_catchLabels.add( 170 new CatchLabelStruct( 171 index.intValue(), 172 exceptionClassInfo, 173 classAdapter.m_callerClassInfo, 174 info 175 ) 176 ); 177 } 178 } 179 super.visitTryCatchBlock(startLabel, endLabel, handlerLabel, exceptionTypeName); 180 } 181 } 182 183 184 186 private final InstrumentationContext m_ctx; 187 188 191 private final List m_catchLabels; 192 193 196 private int m_labelIndex = -1; 197 198 private Label m_lastLabelForLineNumber = EmittedJoinPoint.NO_LINE_NUMBER; 199 200 206 public HandlerVisitor(final ClassVisitor cv, 207 final InstrumentationContext ctx, 208 final List catchLabels) { 209 super(cv); 210 m_ctx = ctx; 211 m_catchLabels = catchLabels; 212 } 213 214 224 public MethodVisitor visitMethod(final int access, 225 final String name, 226 final String desc, 227 final String signature, 228 final String [] exceptions) { 229 if (name.startsWith(WRAPPER_METHOD_PREFIX)) { 230 return super.visitMethod(access, name, desc, signature, exceptions); 231 } 232 233 MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); 234 return mv == null ? null : new CatchClauseCodeAdapter(mv); 235 } 236 237 242 public class CatchClauseCodeAdapter extends MethodAdapter { 243 244 249 public CatchClauseCodeAdapter(final MethodVisitor ca) { 250 super(ca); 251 } 252 253 public void visitLabel(Label label) { 254 m_lastLabelForLineNumber = label; 255 super.visitLabel(label); 256 257 int index = ++m_labelIndex; 259 CatchLabelStruct catchLabel = null; 260 for (Iterator iterator = m_catchLabels.iterator(); iterator.hasNext();) { 261 CatchLabelStruct aCatchLabel = (CatchLabelStruct) iterator.next(); 262 if (aCatchLabel.labelIndexInWholeClass == index) { 263 catchLabel = aCatchLabel; 264 break; 265 } 266 } 267 if (catchLabel == null) { 268 return; 269 } 270 m_ctx.markAsAdvised(); 272 final String callerTypeName = catchLabel.caller.getName().replace('.', '/'); 273 final String exceptionTypeDesc = catchLabel.exception.getSignature(); 274 final String exceptionTypeName = Type.getType(exceptionTypeDesc).getInternalName(); 275 final int joinPointHash = AsmHelper.calculateClassHash(exceptionTypeDesc); 276 final String joinPointClassName = TransformationUtil.getJoinPointClassName( 277 callerTypeName, 278 catchLabel.callerMember.getName(), 279 catchLabel.callerMember.getSignature(), 280 exceptionTypeName, 281 JoinPointType.HANDLER_INT, 282 joinPointHash 283 ); 284 285 mv.visitInsn(DUP); 289 290 if (Modifier.isStatic(catchLabel.callerMember.getModifiers())) { 292 mv.visitInsn(ACONST_NULL); 293 } else { 294 mv.visitVarInsn(ALOAD, 0); 295 } 296 mv.visitMethodInsn( 299 INVOKESTATIC, joinPointClassName, INVOKE_METHOD_NAME, 300 TransformationUtil.getInvokeSignatureForHandlerJoinPoints(callerTypeName, exceptionTypeName) 301 ); 302 303 m_ctx.addEmittedJoinPoint( 305 new EmittedJoinPoint( 306 JoinPointType.HANDLER_INT, 307 callerTypeName, 308 catchLabel.callerMember.getName(), 309 catchLabel.callerMember.getSignature(), 310 catchLabel.callerMember.getModifiers(), 311 exceptionTypeName, 312 "", 313 exceptionTypeDesc, 314 0, joinPointHash, 316 joinPointClassName, 317 m_lastLabelForLineNumber 318 ) 319 ); 320 } 321 } 322 323 330 static boolean handlerFilter(final Set definitions, final ExpressionContext ctx) { 331 for (Iterator it = definitions.iterator(); it.hasNext();) { 332 if (((SystemDefinition) it.next()).hasPointcut(ctx)) { 333 return false; 334 } else { 335 continue; 336 } 337 } 338 return true; 339 } 340 341 347 private static class CatchLabelStruct { 348 int labelIndexInWholeClass = -1; 349 ClassInfo exception = null; 350 ClassInfo caller = null; 351 MemberInfo callerMember = null; 352 353 private CatchLabelStruct(int indexInClass, ClassInfo exception, ClassInfo caller, MemberInfo callerMember) { 354 labelIndexInWholeClass = indexInClass; 355 this.exception = exception; 356 this.caller = caller; 357 this.callerMember = callerMember; 358 } 359 } 360 } | Popular Tags |