1 8 package org.codehaus.aspectwerkz.transform.inlining.weaver; 9 10 import java.util.Set ; 11 import java.util.Iterator ; 12 import java.util.Collection ; 13 import java.util.HashMap ; 14 15 import org.objectweb.asm.*; 16 import org.codehaus.aspectwerkz.transform.Context; 17 import org.codehaus.aspectwerkz.transform.TransformationConstants; 18 import org.codehaus.aspectwerkz.transform.inlining.ContextImpl; 19 import org.codehaus.aspectwerkz.reflect.ClassInfo; 20 import org.codehaus.aspectwerkz.expression.ExpressionContext; 21 import org.codehaus.aspectwerkz.expression.PointcutType; 22 import org.codehaus.aspectwerkz.expression.ExpressionInfo; 23 import org.codehaus.aspectwerkz.definition.SystemDefinition; 24 import org.codehaus.aspectwerkz.definition.AdviceDefinition; 25 import org.codehaus.aspectwerkz.definition.DeploymentScope; 26 import org.codehaus.aspectwerkz.DeploymentModel; 27 28 33 public class InstanceLevelAspectVisitor extends ClassAdapter implements TransformationConstants { 34 35 private final ContextImpl m_ctx; 36 private final ClassInfo m_classInfo; 37 private boolean m_isAdvised = false; 38 39 46 public InstanceLevelAspectVisitor(final ClassVisitor cv, 47 final ClassInfo classInfo, 48 final Context ctx) { 49 super(cv); 50 m_classInfo = classInfo; 51 m_ctx = (ContextImpl) ctx; 52 } 53 54 63 public void visit(final int version, 64 final int access, 65 final String name, 66 final String superName, 67 final String [] interfaces, 68 final String sourceFile) { 69 70 if (classFilter(m_classInfo, m_ctx.getDefinitions())) { 71 super.visit(version, access, name, superName, interfaces, sourceFile); 72 return; 73 } 74 75 for (int i = 0; i < interfaces.length; i++) { 76 String anInterface = interfaces[i]; 77 if (anInterface.equals(HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME)) { 78 super.visit(version, access, name, superName, interfaces, sourceFile); 79 return; 80 } 81 } 82 String [] newInterfaceArray = new String [interfaces.length + 1]; 83 for (int i = 0; i < interfaces.length; i++) { 84 newInterfaceArray[i] = interfaces[i]; 85 } 86 newInterfaceArray[interfaces.length] = HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME; 87 88 super.visit(version, access, name, superName, newInterfaceArray, sourceFile); 90 91 addAspectMapField(); 93 94 addGetAspectMethod(name); 96 } 97 98 108 public CodeVisitor visitMethod(final int access, 109 final String name, 110 final String desc, 111 final String [] exceptions, 112 final Attribute attrs) { 113 if (m_isAdvised) { 114 if (name.equals(INIT_METHOD_NAME)) { 115 CodeVisitor mv = new AppendToInitMethodCodeAdapter( 116 cv.visitMethod(access, name, desc, exceptions, attrs), 117 name 118 ); 119 mv.visitMaxs(0, 0); 120 return mv; 121 } 122 } 123 return cv.visitMethod(access, name, desc, exceptions, attrs); 124 } 125 126 129 private void addAspectMapField() { 130 super.visitField( 131 ACC_PRIVATE + ACC_SYNTHETIC + ACC_TRANSIENT, 132 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 133 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE, 134 null, null 135 ); 136 } 137 138 143 private void addGetAspectMethod(final String name) { 144 CodeVisitor cv = super.visitMethod( 145 ACC_PUBLIC + ACC_SYNTHETIC, 146 GET_INSTANCE_LEVEL_ASPECT_METHOD_NAME, 147 GET_INSTANCE_LEVEL_ASPECT_METHOD_SIGNATURE, 148 null, null 149 ); 150 151 cv.visitVarInsn(ALOAD, 0); 152 cv.visitFieldInsn( 153 GETFIELD, 154 name, 155 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 156 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE 157 ); 158 159 Label ifFieldNullNotLabel = new Label(); 161 cv.visitJumpInsn(IFNONNULL, ifFieldNullNotLabel); 162 cv.visitVarInsn(ALOAD, 0); 163 cv.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME); 164 cv.visitInsn(DUP); 165 cv.visitMethodInsn( 166 INVOKESPECIAL, 167 HASH_MAP_CLASS_NAME, 168 INIT_METHOD_NAME, 169 NO_PARAM_RETURN_VOID_SIGNATURE 170 ); 171 cv.visitFieldInsn( 172 PUTFIELD, 173 m_classInfo.getName().replace('.', '/'), 174 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 175 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE 176 ); 177 cv.visitLabel(ifFieldNullNotLabel); 178 179 cv.visitVarInsn(ALOAD, 0); 180 cv.visitFieldInsn( 181 GETFIELD, 182 name, 183 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 184 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE 185 ); 186 187 cv.visitVarInsn(ALOAD, 2); cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, GET_METHOD_NAME, GET_METHOD_SIGNATURE); 189 cv.visitVarInsn(ASTORE, 4); 190 cv.visitVarInsn(ALOAD, 4); 191 Label ifNullNotLabel = new Label(); 192 cv.visitJumpInsn(IFNONNULL, ifNullNotLabel); 193 cv.visitVarInsn(ALOAD, 2); cv.visitVarInsn(ALOAD, 3); cv.visitVarInsn(ALOAD, 0); cv.visitMethodInsn( 197 INVOKESTATIC, 198 ASPECTS_CLASS_NAME, 199 ASPECT_OF_METHOD_NAME, 200 ASPECT_OF_PER_INSTANCE_METHOD_SIGNATURE 201 ); 202 cv.visitVarInsn(ASTORE, 4); 203 cv.visitVarInsn(ALOAD, 0); 204 cv.visitFieldInsn( 205 GETFIELD, 206 name, 207 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 208 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE 209 ); 210 cv.visitVarInsn(ALOAD, 2); 211 cv.visitVarInsn(ALOAD, 4); 212 cv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS_NAME, PUT_METHOD_NAME, PUT_METHOD_SIGNATURE); 213 cv.visitInsn(POP); 214 cv.visitLabel(ifNullNotLabel); 215 cv.visitVarInsn(ALOAD, 4); 216 cv.visitInsn(ARETURN); 217 cv.visitMaxs(0, 0); 218 219 m_ctx.markAsAdvised(); 220 m_isAdvised = true; 221 } 222 223 230 public static boolean classFilter(final ClassInfo classInfo, final Set definitions) { 231 if (classInfo.isInterface()) { 232 return true; 233 } 234 235 ExpressionContext ctx = new ExpressionContext(PointcutType.WITHIN, null, classInfo); 236 237 for (Iterator it = definitions.iterator(); it.hasNext();) { 238 SystemDefinition systemDef = (SystemDefinition) it.next(); 239 String className = classInfo.getName().replace('/', '.'); 240 if (systemDef.inExcludePackage(className)) { 241 return true; 242 } 243 if (!systemDef.inIncludePackage(className)) { 244 return true; 245 } 246 247 Collection adviceDefs = systemDef.getAdviceDefinitions(); 249 for (Iterator defs = adviceDefs.iterator(); defs.hasNext();) { 250 AdviceDefinition adviceDef = (AdviceDefinition) defs.next(); 251 ExpressionInfo expressionInfo = adviceDef.getExpressionInfo(); 252 if (expressionInfo == null) { 253 continue; 254 } 255 if (adviceDef.getAspectDefinition().getDeploymentModel().equals(DeploymentModel.PER_INSTANCE) 256 && expressionInfo.getAdvisedClassFilterExpression().match(ctx)) { 257 return false; 258 } 259 } 260 261 Collection deploymentScopes = systemDef.getDeploymentScopes(); 263 for (Iterator scopes = deploymentScopes.iterator(); scopes.hasNext();) { 264 DeploymentScope deploymentScope = (DeploymentScope) scopes.next(); 265 ExpressionInfo expression = new ExpressionInfo( 266 deploymentScope.getExpression(), 267 systemDef.getUuid() 268 ); 269 if (expression.getAdvisedClassFilterExpression().match(ctx)) { 270 return false; 271 } 272 } 273 } 274 275 return true; 276 } 277 278 283 private class AppendToInitMethodCodeAdapter extends AfterObjectInitializationCodeAdapter { 284 285 private boolean m_done = false; 286 287 public AppendToInitMethodCodeAdapter(final CodeVisitor ca, String callerMemberName) { 288 super(ca, callerMemberName); 289 } 290 291 299 public void visitMethodInsn(int opcode, 300 String owner, 301 String name, 302 String desc) { 303 super.visitMethodInsn(opcode, owner, name, desc); 304 if (opcode == INVOKESPECIAL && m_isObjectInitialized && !m_done) { 305 m_done = true; 306 307 cv.visitVarInsn(ALOAD, 0); 309 cv.visitTypeInsn(NEW, HASH_MAP_CLASS_NAME); 310 cv.visitInsn(DUP); 311 cv.visitMethodInsn( 312 INVOKESPECIAL, 313 HASH_MAP_CLASS_NAME, 314 INIT_METHOD_NAME, 315 NO_PARAM_RETURN_VOID_SIGNATURE 316 ); 317 cv.visitFieldInsn( 318 PUTFIELD, 319 m_classInfo.getName().replace('.', '/'), 320 INSTANCE_LEVEL_ASPECT_MAP_FIELD_NAME, 321 INSTANCE_LEVEL_ASPECT_MAP_FIELD_SIGNATURE 322 ); 323 } 324 } 325 } 326 } | Popular Tags |