1 4 package com.tc.object.bytecode.hook.impl; 5 6 import com.tc.asm.ClassReader; 7 import com.tc.asm.ClassVisitor; 8 import com.tc.asm.ClassWriter; 9 import com.tc.asm.commons.SerialVersionUIDAdder; 10 import com.tc.aspectwerkz.definition.SystemDefinition; 11 import com.tc.aspectwerkz.definition.deployer.StandardAspectModuleDeployer; 12 import com.tc.aspectwerkz.exception.WrappedRuntimeException; 13 import com.tc.aspectwerkz.expression.ExpressionContext; 14 import com.tc.aspectwerkz.expression.PointcutType; 15 import com.tc.aspectwerkz.reflect.ClassInfo; 16 import com.tc.aspectwerkz.reflect.ClassInfoHelper; 17 import com.tc.aspectwerkz.reflect.impl.asm.AsmClassInfo; 18 import com.tc.aspectwerkz.transform.InstrumentationContext; 19 import com.tc.aspectwerkz.transform.WeavingStrategy; 20 import com.tc.aspectwerkz.transform.inlining.AsmHelper; 21 import com.tc.aspectwerkz.transform.inlining.weaver.AddInterfaceVisitor; 22 import com.tc.aspectwerkz.transform.inlining.weaver.AddMixinMethodsVisitor; 23 import com.tc.aspectwerkz.transform.inlining.weaver.AddWrapperVisitor; 24 import com.tc.aspectwerkz.transform.inlining.weaver.AlreadyAddedMethodAdapter; 25 import com.tc.aspectwerkz.transform.inlining.weaver.ConstructorBodyVisitor; 26 import com.tc.aspectwerkz.transform.inlining.weaver.ConstructorCallVisitor; 27 import com.tc.aspectwerkz.transform.inlining.weaver.FieldSetFieldGetVisitor; 28 import com.tc.aspectwerkz.transform.inlining.weaver.HandlerVisitor; 29 import com.tc.aspectwerkz.transform.inlining.weaver.InstanceLevelAspectVisitor; 30 import com.tc.aspectwerkz.transform.inlining.weaver.JoinPointInitVisitor; 31 import com.tc.aspectwerkz.transform.inlining.weaver.LabelToLineNumberVisitor; 32 import com.tc.aspectwerkz.transform.inlining.weaver.MethodCallVisitor; 33 import com.tc.aspectwerkz.transform.inlining.weaver.MethodExecutionVisitor; 34 import com.tc.aspectwerkz.transform.inlining.weaver.StaticInitializationVisitor; 35 import com.tc.exception.TCLogicalSubclassNotPortableException; 36 import com.tc.object.config.DSOClientConfigHelper; 37 import com.tc.object.logging.InstrumentationLogger; 38 import com.tc.object.logging.InstrumentationLoggerImpl; 39 import com.tc.util.AdaptedClassDumper; 40 41 import java.util.ArrayList ; 42 import java.util.HashMap ; 43 import java.util.HashSet ; 44 import java.util.Iterator ; 45 import java.util.List ; 46 import java.util.Map ; 47 import java.util.Set ; 48 49 55 public class DefaultWeavingStrategy implements WeavingStrategy { 56 57 private final DSOClientConfigHelper m_configHelper; 58 private final InstrumentationLogger m_logger; 59 private final InstrumentationLogger m_instrumentationLogger; 60 61 public DefaultWeavingStrategy(final DSOClientConfigHelper configHelper, InstrumentationLogger instrumentationLogger) { 62 m_configHelper = configHelper; 63 m_instrumentationLogger = instrumentationLogger; 64 m_logger = new InstrumentationLoggerImpl(m_configHelper.getInstrumentationLoggingOptions()); 65 66 StandardAspectModuleDeployer.deploy(getClass().getClassLoader(), StandardAspectModuleDeployer.ASPECT_MODULES); 68 } 69 70 76 public void transform(String className, final InstrumentationContext context) { 77 try { 78 final byte[] bytecode = context.getInitialBytecode(); 79 final ClassLoader loader = context.getLoader(); 80 81 Map aspectModules = m_configHelper.getAspectModules(); 82 for (Iterator it = aspectModules.entrySet().iterator(); it.hasNext();) { 83 Map.Entry e = (Map.Entry ) it.next(); 84 if (className.startsWith((String ) e.getKey())) { 85 List modules = (List ) e.getValue(); 86 for (Iterator it2 = modules.iterator(); it2.hasNext();) { 87 StandardAspectModuleDeployer.deploy(loader, (String ) it2.next()); 88 } 89 } 90 } 91 92 ClassInfo classInfo = AsmClassInfo.getClassInfo(className, bytecode, loader); 93 94 if (classInfo.getName().startsWith("$") && classInfo.getSuperclass().getName().equals("java.lang.reflect.Proxy")) { 99 context.setCurrentBytecode(context.getInitialBytecode()); 100 return; 101 } 102 103 if (context.isProxy() && isInstrumentedByDSO(classInfo)) { 105 context.setCurrentBytecode(context.getInitialBytecode()); 106 return; 107 } 108 109 final boolean isDsoAdaptable = m_configHelper.shouldBeAdapted(classInfo); 119 120 final Set definitions = context.getDefinitions(); 122 final ExpressionContext[] ctxs = new ExpressionContext[] { 123 new ExpressionContext(PointcutType.EXECUTION, classInfo, classInfo), 124 new ExpressionContext(PointcutType.CALL, null, classInfo), 125 new ExpressionContext(PointcutType.GET, null, classInfo), 126 new ExpressionContext(PointcutType.SET, null, classInfo), 127 new ExpressionContext(PointcutType.HANDLER, null, classInfo), 128 new ExpressionContext(PointcutType.STATIC_INITIALIZATION, classInfo, classInfo), 129 new ExpressionContext(PointcutType.WITHIN, classInfo, classInfo) }; 130 131 final boolean isAdvisable = !classFilter(definitions, ctxs, classInfo); 133 134 if (!isAdvisable && !isDsoAdaptable) { 135 context.setCurrentBytecode(context.getInitialBytecode()); 136 return; 137 } 138 139 if (m_instrumentationLogger.classInclusion()) { 140 m_instrumentationLogger.classIncluded(className); 141 } 142 143 if (isAdvisable) { 146 final boolean filterForCall = classFilterFor(definitions, new ExpressionContext[] { 148 new ExpressionContext(PointcutType.CALL, null, classInfo), 149 new ExpressionContext(PointcutType.WITHIN, classInfo, classInfo) }); final boolean filterForGetSet = classFilterFor(definitions, new ExpressionContext[] { 152 new ExpressionContext(PointcutType.GET, null, classInfo), 153 new ExpressionContext(PointcutType.SET, null, classInfo), 154 new ExpressionContext(PointcutType.WITHIN, classInfo, classInfo) }); final boolean filterForHandler = classFilterFor(definitions, new ExpressionContext[] { 157 new ExpressionContext(PointcutType.HANDLER, null, classInfo), 158 new ExpressionContext(PointcutType.WITHIN, classInfo, classInfo) }); 161 boolean filterForStaticinitialization = !classInfo.hasStaticInitializer() 163 || classFilterFor( 164 definitions, 165 new ExpressionContext[] { new ExpressionContext( 166 PointcutType.STATIC_INITIALIZATION, 167 classInfo 168 .staticInitializer(), 169 classInfo) }); 170 if (!filterForStaticinitialization) { 171 filterForStaticinitialization = !hasPointcut(definitions, 172 new ExpressionContext(PointcutType.STATIC_INITIALIZATION, 173 classInfo.staticInitializer(), classInfo)); 174 } 175 176 final ClassReader crLookahead = new ClassReader(bytecode); 178 HashMap newInvocationsByCallerMemberHash = null; 179 if (!filterForCall) { 180 newInvocationsByCallerMemberHash = new HashMap (); 181 crLookahead.accept( 182 new ConstructorCallVisitor.LookaheadNewDupInvokeSpecialInstructionClassAdapter(newInvocationsByCallerMemberHash), 183 true); 184 } 185 186 List catchLabels = new ArrayList (); 188 if (!filterForHandler) { 189 final ClassWriter cw2 = AsmHelper.newClassWriter(true); 190 HandlerVisitor.LookaheadCatchLabelsClassAdapter lookForCatches = new HandlerVisitor.LookaheadCatchLabelsClassAdapter(cw2, loader, classInfo, context, catchLabels); 192 final ClassReader crLookahead2 = new ClassReader(bytecode); 194 crLookahead2.accept(lookForCatches, null, false); 195 } 196 197 Set addedMethods = new HashSet (); 200 crLookahead.accept(new AlreadyAddedMethodAdapter(addedMethods), true); 201 202 final ClassWriter writerPhase1 = AsmHelper.newClassWriter(true); 205 ClassVisitor reversedChainPhase1 = new AddMixinMethodsVisitor(writerPhase1, classInfo, context, addedMethods); 206 reversedChainPhase1 = new AddInterfaceVisitor(reversedChainPhase1, classInfo, context); 207 final ClassReader readerPhase1 = new ClassReader(bytecode); 208 readerPhase1.accept(reversedChainPhase1, null, false); 209 context.setCurrentBytecode(writerPhase1.toByteArray()); 210 211 classInfo = AsmClassInfo.newClassInfo(context.getCurrentBytecode(), loader); 214 215 final ClassWriter writerPhase2 = AsmHelper.newClassWriter(true); 218 ClassVisitor reversedChainPhase2 = new InstanceLevelAspectVisitor(writerPhase2, classInfo, context); 219 reversedChainPhase2 = new MethodExecutionVisitor(reversedChainPhase2, classInfo, context, addedMethods); 220 reversedChainPhase2 = new ConstructorBodyVisitor(reversedChainPhase2, classInfo, context, addedMethods); 221 if (!filterForStaticinitialization) { 222 reversedChainPhase2 = new StaticInitializationVisitor(reversedChainPhase2, context, addedMethods); 223 } 224 reversedChainPhase2 = new HandlerVisitor(reversedChainPhase2, context, catchLabels); 225 if (!filterForCall) { 226 reversedChainPhase2 = new MethodCallVisitor(reversedChainPhase2, loader, classInfo, context); 227 reversedChainPhase2 = new ConstructorCallVisitor(reversedChainPhase2, loader, classInfo, context, 228 newInvocationsByCallerMemberHash); 229 } 230 if (!filterForGetSet) { 231 reversedChainPhase2 = new FieldSetFieldGetVisitor(reversedChainPhase2, loader, classInfo, context); 232 } 233 reversedChainPhase2 = new LabelToLineNumberVisitor(reversedChainPhase2, context); 234 235 final ClassReader readerPhase2 = new ClassReader(context.getCurrentBytecode()); 236 readerPhase2.accept(reversedChainPhase2, null, false); 237 context.setCurrentBytecode(writerPhase2.toByteArray()); 238 239 if (context.isAdvised()) { 242 final ClassWriter writerPhase3 = AsmHelper.newClassWriter(true); 243 ClassVisitor reversedChainPhase3 = new AddWrapperVisitor(writerPhase3, context, addedMethods); 244 reversedChainPhase3 = new JoinPointInitVisitor(reversedChainPhase3, context); 245 ClassReader readerPhase3 = new ClassReader(context.getCurrentBytecode()); 246 readerPhase3.accept(reversedChainPhase3, null, false); 247 context.setCurrentBytecode(writerPhase3.toByteArray()); 248 } 249 } 250 251 if (isDsoAdaptable) { 254 final ClassWriter dsoWriter = AsmHelper.newClassWriter(true); 255 ClassVisitor dsoVisitor = m_configHelper.createClassAdapterFor(dsoWriter, classInfo, m_logger, loader); 256 257 final ClassReader dsoReader = new ClassReader(context.getCurrentBytecode()); 258 try { 259 dsoReader.accept(dsoVisitor, false); 260 context.setCurrentBytecode(dsoWriter.toByteArray()); 261 } catch (TCLogicalSubclassNotPortableException e) { 262 List l = new ArrayList (1); 263 l.add(e.getSuperClassName()); 264 m_logger.subclassOfLogicallyManagedClasses(e.getClassName(), l); 265 } 266 } 267 268 if (context.isAdvised() || isDsoAdaptable) { 271 if (ClassInfoHelper.implementsInterface(classInfo, "java.io.Serializable")) { 272 final ClassWriter writerPhase3 = AsmHelper.newClassWriter(true); 273 ClassReader readerPhase3 = new ClassReader(context.getCurrentBytecode()); 274 readerPhase3.accept(new SerialVersionUIDAdder(writerPhase3), false); 275 context.setCurrentBytecode(writerPhase3.toByteArray()); 276 } 277 } 278 279 AdaptedClassDumper.write(className, context.getCurrentBytecode()); 280 } catch (Throwable t) { 281 t.printStackTrace(); 282 throw new WrappedRuntimeException(t); 283 } 284 } 285 286 private boolean isInstrumentedByDSO(ClassInfo classInfo) { 287 ClassInfo[] interfaces = classInfo.getInterfaces(); 288 for (int i = 0; i < interfaces.length; i++) { 289 if (interfaces[i].getName().equals("com.tc.object.bytecode.TransparentAccess")) { return true; } 290 } 291 return false; 292 } 293 294 302 private static boolean classFilter(final Set definitions, final ExpressionContext[] ctxs, final ClassInfo classInfo) { 303 if (classInfo.isInterface()) { return true; } 304 for (Iterator defs = definitions.iterator(); defs.hasNext();) { 305 if (!classFilter((SystemDefinition) defs.next(), ctxs, classInfo)) { return false; } 306 } 307 return true; 308 } 309 310 320 private static boolean classFilter(final SystemDefinition definition, final ExpressionContext[] ctxs, 321 final ClassInfo classInfo) { 322 if (classInfo.isInterface()) { return true; } 323 String className = classInfo.getName(); 324 if (definition.inExcludePackage(className)) { return true; } 325 if (!definition.inIncludePackage(className)) { return true; } 326 if (definition.isAdvised(ctxs)) { return false; } 327 if (definition.hasMixin(ctxs)) { return false; } 328 if (definition.hasIntroducedInterface(ctxs)) { return false; } 329 return !definition.inPreparePackage(className); 330 } 331 332 private static boolean classFilterFor(final Set definitions, final ExpressionContext[] ctxs) { 333 for (Iterator defs = definitions.iterator(); defs.hasNext();) { 334 if (!classFilterFor((SystemDefinition) defs.next(), ctxs)) { return false; } 335 } 336 return true; 337 } 338 339 private static boolean classFilterFor(final SystemDefinition definition, final ExpressionContext[] ctxs) { 340 return !definition.isAdvised(ctxs); 341 } 342 343 private static boolean hasPointcut(final Set definitions, final ExpressionContext ctx) { 344 for (Iterator defs = definitions.iterator(); defs.hasNext();) { 345 if (hasPointcut((SystemDefinition) defs.next(), ctx)) { return true; } 346 } 347 return false; 348 } 349 350 private static boolean hasPointcut(final SystemDefinition definition, final ExpressionContext ctx) { 351 return definition.hasPointcut(ctx); 352 } 353 } 354 | Popular Tags |