1 8 package org.codehaus.aspectwerkz.transform.inlining; 9 10 import gnu.trove.TLongObjectHashMap; 11 12 import java.util.ArrayList ; 13 import java.util.HashSet ; 14 import java.util.Iterator ; 15 import java.util.List ; 16 import java.util.Set ; 17 18 import org.codehaus.aspectwerkz.definition.SystemDefinition; 19 import org.codehaus.aspectwerkz.exception.WrappedRuntimeException; 20 import org.codehaus.aspectwerkz.expression.ExpressionContext; 21 import org.codehaus.aspectwerkz.expression.PointcutType; 22 import org.codehaus.aspectwerkz.reflect.ClassInfo; 23 import org.codehaus.aspectwerkz.reflect.impl.asm.AsmClassInfo; 24 import org.codehaus.aspectwerkz.transform.Context; 25 import org.codehaus.aspectwerkz.transform.WeavingStrategy; 26 import org.codehaus.aspectwerkz.transform.inlining.weaver.AddInterfaceVisitor; 27 import org.codehaus.aspectwerkz.transform.inlining.weaver.AddMixinMethodsVisitor; 28 import org.codehaus.aspectwerkz.transform.inlining.weaver.AlreadyAddedMethodAdapter; 29 import org.codehaus.aspectwerkz.transform.inlining.weaver.ConstructorBodyVisitor; 30 import org.codehaus.aspectwerkz.transform.inlining.weaver.ConstructorCallVisitor; 31 import org.codehaus.aspectwerkz.transform.inlining.weaver.FieldSetFieldGetVisitor; 32 import org.codehaus.aspectwerkz.transform.inlining.weaver.HandlerVisitor; 33 import org.codehaus.aspectwerkz.transform.inlining.weaver.InstanceLevelAspectVisitor; 34 import org.codehaus.aspectwerkz.transform.inlining.weaver.JoinPointInitVisitor; 35 import org.codehaus.aspectwerkz.transform.inlining.weaver.LabelToLineNumberVisitor; 36 import org.codehaus.aspectwerkz.transform.inlining.weaver.MethodCallVisitor; 37 import org.codehaus.aspectwerkz.transform.inlining.weaver.MethodExecutionVisitor; 38 import org.codehaus.aspectwerkz.transform.inlining.weaver.StaticInitializationVisitor; 39 import org.codehaus.aspectwerkz.transform.inlining.weaver.SerialVersionUidVisitor; 40 import org.codehaus.aspectwerkz.transform.inlining.weaver.AddWrapperVisitor; 41 import org.objectweb.asm.ClassReader; 42 import org.objectweb.asm.ClassVisitor; 43 import org.objectweb.asm.ClassWriter; 44 import org.objectweb.asm.attrs.Attributes; 45 46 52 public class InliningWeavingStrategy implements WeavingStrategy { 53 54 60 public void transform(String className, final Context context) { 61 try { 62 final byte[] bytecode = context.getInitialBytecode(); 63 final ClassLoader loader = context.getLoader(); 64 65 ClassInfo classInfo = AsmClassInfo.getClassInfo(bytecode, loader); 66 67 if (classInfo.getName().startsWith("$") && classInfo.getSuperclass().getName().equals("java.lang.reflect.Proxy")) { 72 context.setCurrentBytecode(context.getInitialBytecode()); 73 return; 74 } 75 76 final Set definitions = context.getDefinitions(); 78 final ExpressionContext[] ctxs = new ExpressionContext[]{ 79 new ExpressionContext(PointcutType.EXECUTION, classInfo, classInfo), 80 new ExpressionContext(PointcutType.CALL, null, classInfo), 81 new ExpressionContext(PointcutType.GET, null, classInfo), 82 new ExpressionContext(PointcutType.SET, null, classInfo), 83 new ExpressionContext(PointcutType.HANDLER, null, classInfo), 84 new ExpressionContext(PointcutType.STATIC_INITIALIZATION, classInfo, classInfo), 85 new ExpressionContext(PointcutType.WITHIN, classInfo, classInfo) 86 }; 87 88 if (classFilter(definitions, ctxs, classInfo)) { 89 return; 90 } 91 92 96 final boolean filterForCall = classFilterFor( 98 definitions, new ExpressionContext[]{ 99 new ExpressionContext(PointcutType.CALL, null, classInfo), 100 new ExpressionContext(PointcutType.WITHIN, classInfo, classInfo) 101 } 102 ); final boolean filterForGetSet = classFilterFor( 104 definitions, new ExpressionContext[]{ 105 new ExpressionContext(PointcutType.GET, null, classInfo), 106 new ExpressionContext(PointcutType.SET, null, classInfo), 107 new ExpressionContext(PointcutType.WITHIN, classInfo, classInfo) 108 } 109 ); final boolean filterForHandler = classFilterFor( 111 definitions, new ExpressionContext[]{ 112 new ExpressionContext(PointcutType.HANDLER, null, classInfo), 113 new ExpressionContext(PointcutType.WITHIN, classInfo, classInfo) 114 } 115 ); 117 boolean filterForStaticinitialization = !classInfo.hasStaticInitializer() 119 || classFilterFor(definitions, new ExpressionContext[] { 120 new ExpressionContext(PointcutType.STATIC_INITIALIZATION, 121 classInfo.staticInitializer(), 122 classInfo) 123 } 124 ); 125 if (!filterForStaticinitialization) { 126 filterForStaticinitialization = !hasPointcut(definitions, new ExpressionContext( 127 PointcutType.STATIC_INITIALIZATION, 128 classInfo.staticInitializer(), 129 classInfo 130 )); 131 } 132 133 final ClassReader crLookahead = new ClassReader(bytecode); 135 TLongObjectHashMap newInvocationsByCallerMemberHash = null; 136 if (!filterForCall) { 137 newInvocationsByCallerMemberHash = new TLongObjectHashMap(); 138 crLookahead.accept( 139 new ConstructorCallVisitor.LookaheadNewDupInvokeSpecialInstructionClassAdapter( 140 newInvocationsByCallerMemberHash 141 ), 142 true 143 ); 144 } 145 146 List catchLabels = new ArrayList (); 148 if (!filterForHandler) { 149 final ClassReader crLookahead2 = new ClassReader(bytecode); 150 final ClassWriter cw2 = AsmHelper.newClassWriter(true); 151 152 HandlerVisitor.LookaheadCatchLabelsClassAdapter lookForCatches = 153 new HandlerVisitor.LookaheadCatchLabelsClassAdapter( 154 cw2, loader, classInfo, context, catchLabels 155 ); 156 crLookahead2.accept(lookForCatches, Attributes.getDefaultAttributes(), false); 158 } 159 160 Set addedMethods = new HashSet (); 163 crLookahead.accept(new AlreadyAddedMethodAdapter(addedMethods), true); 164 165 final ClassWriter writerPhase1 = AsmHelper.newClassWriter(true); 167 final ClassReader readerPhase1 = new ClassReader(bytecode); 168 ClassVisitor reversedChainPhase1 = writerPhase1; 169 reversedChainPhase1 = new AddMixinMethodsVisitor(reversedChainPhase1, classInfo, context, addedMethods); 170 reversedChainPhase1 = new AddInterfaceVisitor(reversedChainPhase1, classInfo, context); 171 readerPhase1.accept(reversedChainPhase1, Attributes.getDefaultAttributes(), false); 172 final byte[] bytesPhase1 = writerPhase1.toByteArray(); 173 174 classInfo = AsmClassInfo.newClassInfo(bytesPhase1, loader); 176 177 final ClassWriter writerPhase2 = AsmHelper.newClassWriter(true); 179 final ClassReader readerPhase2 = new ClassReader(bytesPhase1); 180 ClassVisitor reversedChainPhase2 = writerPhase2; 181 reversedChainPhase2 = new InstanceLevelAspectVisitor(reversedChainPhase2, classInfo, context); 182 reversedChainPhase2 = new MethodExecutionVisitor(reversedChainPhase2, classInfo, context, addedMethods); 183 reversedChainPhase2 = new ConstructorBodyVisitor(reversedChainPhase2, classInfo, context, addedMethods); 184 if(!filterForStaticinitialization) { 185 reversedChainPhase2 = new StaticInitializationVisitor(reversedChainPhase2, context, addedMethods); 186 } 187 reversedChainPhase2 = new HandlerVisitor(reversedChainPhase2, context, catchLabels); 188 if (!filterForCall) { 189 reversedChainPhase2 = new MethodCallVisitor(reversedChainPhase2, loader, classInfo, context); 190 reversedChainPhase2 = new ConstructorCallVisitor( 191 reversedChainPhase2, loader, classInfo, context, newInvocationsByCallerMemberHash 192 ); 193 } 194 if (!filterForGetSet) { 195 reversedChainPhase2 = new FieldSetFieldGetVisitor(reversedChainPhase2, loader, classInfo, context); 196 } 197 reversedChainPhase2 = new LabelToLineNumberVisitor(reversedChainPhase2, context); 198 readerPhase2.accept(reversedChainPhase2, Attributes.getDefaultAttributes(), false); 199 final byte[] bytesPhase2 = writerPhase2.toByteArray(); 200 201 context.setCurrentBytecode(bytesPhase2); 202 203 if (context.isAdvised()) { 205 final ClassWriter writerPhase3 = AsmHelper.newClassWriter(true); 206 ClassReader readerPhase3 = new ClassReader(bytesPhase2); 207 ClassVisitor reversedChainPhase3 = writerPhase3; 208 reversedChainPhase3 = new SerialVersionUidVisitor.Add(reversedChainPhase3, context, classInfo); 209 reversedChainPhase3 = new AddWrapperVisitor(reversedChainPhase3, context, addedMethods); 210 reversedChainPhase3 = new JoinPointInitVisitor(reversedChainPhase3, context); 211 readerPhase3.accept(reversedChainPhase3, Attributes.getDefaultAttributes(), false); 212 final byte[] bytesPhase3 = writerPhase3.toByteArray(); 213 214 context.setCurrentBytecode(bytesPhase3); 215 } 216 217 228 236 244 } catch (Throwable t) { 245 t.printStackTrace(); 246 throw new WrappedRuntimeException(t); 247 } 248 } 249 250 258 public Context newContext(final String name, final byte[] bytecode, final ClassLoader loader) { 259 return new ContextImpl(name, bytecode, loader); 260 } 261 262 270 private static boolean classFilter(final Set definitions, 271 final ExpressionContext[] ctxs, 272 final ClassInfo classInfo) { 273 if (classInfo.isInterface()) { 274 return true; 275 } 276 for (Iterator defs = definitions.iterator(); defs.hasNext();) { 277 if (classFilter((SystemDefinition) defs.next(), ctxs, classInfo)) { 278 continue; 279 } else { 280 return false; 281 } 282 } 283 return true; 284 } 285 286 296 private static boolean classFilter(final SystemDefinition definition, 297 final ExpressionContext[] ctxs, 298 final ClassInfo classInfo) { 299 if (classInfo.isInterface()) { 300 return true; 301 } 302 String className = classInfo.getName(); 303 if (definition.inExcludePackage(className)) { 304 return true; 305 } 306 if (!definition.inIncludePackage(className)) { 307 return true; 308 } 309 if (definition.isAdvised(ctxs)) { 310 return false; 311 } 312 if (definition.hasMixin(ctxs)) { 313 return false; 314 } 315 if (definition.hasIntroducedInterface(ctxs)) { 316 return false; 317 } 318 if (definition.inPreparePackage(className)) { 319 return false; 320 } 321 return true; 322 } 323 324 private static boolean classFilterFor(final Set definitions, 325 final ExpressionContext[] ctxs) { 326 for (Iterator defs = definitions.iterator(); defs.hasNext();) { 327 if (classFilterFor((SystemDefinition) defs.next(), ctxs)) { 328 continue; 329 } else { 330 return false; 331 } 332 } 333 return true; 334 } 335 336 private static boolean classFilterFor(final SystemDefinition definition, 337 final ExpressionContext[] ctxs) { 338 if (definition.isAdvised(ctxs)) { 339 return false; 340 } 341 return true; 342 } 343 344 private static boolean hasPointcut(final Set definitions, 345 final ExpressionContext ctx) { 346 for (Iterator defs = definitions.iterator(); defs.hasNext();) { 347 if (hasPointcut((SystemDefinition) defs.next(), ctx)) { 348 return true; 349 } else { 350 continue; 351 } 352 } 353 return false; 354 } 355 356 private static boolean hasPointcut(final SystemDefinition definition, 357 final ExpressionContext ctx) { 358 if (definition.hasPointcut(ctx)) { 359 return true; 360 } 361 return false; 362 } 363 } | Popular Tags |