1 8 package org.codehaus.aspectwerkz.transform.inlining.weaver; 9 10 import org.objectweb.asm.ClassAdapter; 11 import org.objectweb.asm.ClassVisitor; 12 import org.objectweb.asm.CodeVisitor; 13 import org.objectweb.asm.Attribute; 14 import org.objectweb.asm.CodeAdapter; 15 import org.objectweb.asm.Label; 16 import org.objectweb.asm.Type; 17 import org.codehaus.aspectwerkz.definition.SystemDefinition; 18 import org.codehaus.aspectwerkz.expression.ExpressionContext; 19 import org.codehaus.aspectwerkz.expression.PointcutType; 20 import org.codehaus.aspectwerkz.joinpoint.management.JoinPointType; 21 import org.codehaus.aspectwerkz.reflect.ClassInfo; 22 import org.codehaus.aspectwerkz.reflect.MemberInfo; 23 import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo; 24 import org.codehaus.aspectwerkz.transform.Context; 25 import org.codehaus.aspectwerkz.transform.TransformationUtil; 26 import org.codehaus.aspectwerkz.transform.TransformationConstants; 27 import org.codehaus.aspectwerkz.transform.inlining.ContextImpl; 28 import org.codehaus.aspectwerkz.transform.inlining.AsmHelper; 29 import org.codehaus.aspectwerkz.transform.inlining.EmittedJoinPoint; 30 31 import java.util.Iterator ; 32 import java.util.Set ; 33 import java.util.ArrayList ; 34 import java.util.List ; 35 import java.util.Map ; 36 import java.util.HashMap ; 37 import java.lang.reflect.Modifier ; 38 39 44 public class HandlerVisitor extends ClassAdapter implements TransformationConstants { 45 46 52 public static class LookaheadCatchLabelsClassAdapter extends ClassAdapter { 53 56 List m_catchLabels = new ArrayList (); 57 58 61 private final Map m_labelIndexes = new HashMap (); 62 63 66 private int m_labelIndex = -1; 67 68 private final ContextImpl m_ctx; 69 private final ClassLoader m_loader; 70 private final ClassInfo m_callerClassInfo; 71 72 81 public LookaheadCatchLabelsClassAdapter(ClassVisitor cv, ClassLoader loader, ClassInfo callerClassInfo, 82 Context ctx, List catchLabels) { 83 super(cv); 84 m_catchLabels = catchLabels; 85 m_loader = loader; 86 m_callerClassInfo = callerClassInfo; 87 m_ctx = (ContextImpl) ctx; 88 } 89 90 100 public CodeVisitor visitMethod(final int access, 101 final String callerMethodName, 102 final String callerMethodDesc, 103 final String [] exceptions, 104 final Attribute attrs) { 105 if (callerMethodName.startsWith(WRAPPER_METHOD_PREFIX)) { 106 return super.visitMethod(access, callerMethodName, callerMethodDesc, exceptions, attrs); 107 } 108 109 CodeVisitor mv = cv.visitMethod(access, callerMethodName, callerMethodDesc, exceptions, attrs); 110 if (mv == null) { 111 return mv; 112 } 113 114 final MemberInfo callerMemberInfo; 115 if (CLINIT_METHOD_NAME.equals(callerMethodName)) { 116 callerMemberInfo = m_callerClassInfo.staticInitializer(); 117 } else if (INIT_METHOD_NAME.equals(callerMethodName)) { 118 int hash = AsmHelper.calculateConstructorHash(callerMethodDesc); 119 callerMemberInfo = m_callerClassInfo.getConstructor(hash); 120 } else { 121 int hash = AsmHelper.calculateMethodHash(callerMethodName, callerMethodDesc); 122 callerMemberInfo = m_callerClassInfo.getMethod(hash); 123 } 124 if (callerMemberInfo == null) { 125 System.err.println( 126 "AW::WARNING " + 127 "metadata structure could not be build for method [" 128 + m_callerClassInfo.getName().replace('/', '.') 129 + '.' + callerMethodName + ':' + callerMethodDesc + ']' 130 ); 131 return mv; 132 } 133 134 140 return new CodeAdapter(mv) { 141 public void visitLabel(Label label) { 142 m_labelIndexes.put(label, new Integer (++m_labelIndex)); 143 super.visitLabel(label); 144 } 145 146 public void visitTryCatchBlock(Label startLabel, Label endLabel, Label handlerLabel, 147 String exceptionTypeName) { 148 if (exceptionTypeName == null) { 149 super.visitTryCatchBlock(startLabel, endLabel, handlerLabel, exceptionTypeName); 151 return; 152 } 153 final ClassInfo exceptionClassInfo = AsmClassInfo.getClassInfo(exceptionTypeName, m_loader); 154 final ExpressionContext ctx = new ExpressionContext( 155 PointcutType.HANDLER, exceptionClassInfo, callerMemberInfo 156 ); 157 if (!handlerFilter(m_ctx.getDefinitions(), ctx)) { 158 Integer index = (Integer ) m_labelIndexes.get(handlerLabel); 160 if (index != null) { 161 m_catchLabels.add( 162 new CatchLabelStruct( 163 index.intValue(), 164 exceptionClassInfo, 165 m_callerClassInfo, 166 callerMemberInfo 167 ) 168 ); 169 } 170 } 171 super.visitTryCatchBlock(startLabel, endLabel, handlerLabel, exceptionTypeName); 172 } 173 }; 174 } 175 } 176 177 179 private final ContextImpl m_ctx; 180 181 184 private final List m_catchLabels; 185 186 189 private int m_labelIndex = -1; 190 191 private Label m_lastLabelForLineNumber = EmittedJoinPoint.NO_LINE_NUMBER; 192 193 194 200 public HandlerVisitor(final ClassVisitor cv, 201 final Context ctx, 202 final List catchLabels) { 203 super(cv); 204 m_ctx = (ContextImpl) ctx; 205 m_catchLabels = catchLabels; 206 } 207 208 218 public CodeVisitor visitMethod(final int access, 219 final String name, 220 final String desc, 221 final String [] exceptions, 222 final Attribute attrs) { 223 if (name.startsWith(WRAPPER_METHOD_PREFIX)) { 224 return super.visitMethod(access, name, desc, exceptions, attrs); 225 } 226 227 CodeVisitor mv = cv.visitMethod(access, name, desc, exceptions, attrs); 228 return mv == null ? null : new CatchClauseCodeAdapter(mv); 229 } 230 231 236 public class CatchClauseCodeAdapter extends CodeAdapter { 237 238 243 public CatchClauseCodeAdapter(final CodeVisitor ca) { 244 super(ca); 245 } 246 247 public void visitLabel(Label label) { 248 m_lastLabelForLineNumber = label; 249 super.visitLabel(label); 250 251 int index = ++m_labelIndex; 253 CatchLabelStruct catchLabel = null; 254 for (Iterator iterator = m_catchLabels.iterator(); iterator.hasNext();) { 255 CatchLabelStruct aCatchLabel = (CatchLabelStruct) iterator.next(); 256 if (aCatchLabel.labelIndexInWholeClass == index) { 257 catchLabel = aCatchLabel; 258 break; 259 } 260 } 261 if (catchLabel == null) { 262 return; 263 } 264 m_ctx.markAsAdvised(); 266 final String callerTypeName = catchLabel.caller.getName().replace('.', '/'); 267 final String exceptionTypeDesc = catchLabel.exception.getSignature(); 268 final String exceptionTypeName = Type.getType(exceptionTypeDesc).getInternalName(); 269 final int joinPointHash = AsmHelper.calculateClassHash(exceptionTypeDesc); 270 final String joinPointClassName = TransformationUtil.getJoinPointClassName( 271 callerTypeName, 272 catchLabel.callerMember.getName(), 273 catchLabel.callerMember.getSignature(), 274 exceptionTypeName, 275 JoinPointType.HANDLER_INT, 276 joinPointHash 277 ); 278 279 cv.visitInsn(DUP); 283 284 if (Modifier.isStatic(catchLabel.callerMember.getModifiers())) { 286 cv.visitInsn(ACONST_NULL); 287 } else { 288 cv.visitVarInsn(ALOAD, 0); 289 } 290 cv.visitMethodInsn( 293 INVOKESTATIC, joinPointClassName, INVOKE_METHOD_NAME, 294 TransformationUtil.getInvokeSignatureForHandlerJoinPoints(callerTypeName, exceptionTypeName) 295 ); 296 297 m_ctx.addEmittedJoinPoint( 299 new EmittedJoinPoint( 300 JoinPointType.HANDLER_INT, 301 callerTypeName, 302 catchLabel.callerMember.getName(), 303 catchLabel.callerMember.getSignature(), 304 catchLabel.callerMember.getModifiers(), 305 exceptionTypeName, 306 "", 307 exceptionTypeDesc, 308 0, joinPointHash, 310 joinPointClassName, 311 m_lastLabelForLineNumber 312 ) 313 ); 314 } 315 } 316 317 324 static boolean handlerFilter(final Set definitions, final ExpressionContext ctx) { 325 for (Iterator it = definitions.iterator(); it.hasNext();) { 326 if (((SystemDefinition) it.next()).hasPointcut(ctx)) { 327 return false; 328 } else { 329 continue; 330 } 331 } 332 return true; 333 } 334 335 341 private static class CatchLabelStruct { 342 int labelIndexInWholeClass = -1; 343 ClassInfo exception = null; 344 ClassInfo caller = null; 345 MemberInfo callerMember = null; 346 347 private CatchLabelStruct(int indexInClass, ClassInfo exception, ClassInfo caller, MemberInfo callerMember) { 348 labelIndexInWholeClass = indexInClass; 349 this.exception = exception; 350 this.caller = caller; 351 this.callerMember = callerMember; 352 } 353 } 354 } | Popular Tags |