/** * Adds the mixin field to the target class. * * @param fieldInfo * @param deploymentModel * @param mixinDef */ private void addMixinField( final MixinFieldInfo fieldInfo, final DeploymentModel deploymentModel, final MixinDefinition mixinDef) { final String signature = fieldInfo.mixinClassInfo.getSignature(); int modifiers = 0; if (deploymentModel.equals(DeploymentModel.PER_CLASS) || deploymentModel.equals(DeploymentModel.PER_JVM)) { fieldInfo.isStatic = true; fieldInfo.isPerJVM = deploymentModel.equals(DeploymentModel.PER_JVM); modifiers = ACC_PRIVATE + ACC_FINAL + ACC_STATIC + ACC_SYNTHETIC; } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) { fieldInfo.isStatic = false; modifiers = ACC_PRIVATE + ACC_FINAL + ACC_SYNTHETIC; } else { throw new DefinitionException( "deployment model [" + mixinDef.getDeploymentModel() + "] for mixin [" + mixinDef.getMixinImpl().getName() + "] is not supported"); } if (mixinDef.isTransient()) { modifiers += ACC_TRANSIENT; } cv.visitField(modifiers, fieldInfo.fieldName, signature, null, null); m_mixinFields.put(mixinDef.getMixinImpl(), fieldInfo); }
/** Adds mixin fields and methods to the target class. */ private void addMixinMembers() { int index = 0; for (Iterator it = m_ctx.getDefinitions().iterator(); it.hasNext(); ) { List mixinDefs = ((SystemDefinition) it.next()).getMixinDefinitions(m_expressionContext); // check for method clashes Set interfaceSet = new HashSet(); for (Iterator it2 = mixinDefs.iterator(); it2.hasNext(); ) { interfaceSet.addAll(((MixinDefinition) it2.next()).getInterfaceClassNames()); } // FIXME AVP refactor to handle precedence injection // if (ClassInfoHelper.hasMethodClash(interfaceSet, m_ctx.getLoader())) { // return; // } for (Iterator it2 = mixinDefs.iterator(); it2.hasNext(); ) { final MixinDefinition mixinDef = (MixinDefinition) it2.next(); final ClassInfo mixinImpl = mixinDef.getMixinImpl(); final DeploymentModel deploymentModel = mixinDef.getDeploymentModel(); if (m_mixinFields.containsKey(mixinImpl)) { continue; } final MixinFieldInfo fieldInfo = new MixinFieldInfo(); fieldInfo.fieldName = MIXIN_FIELD_NAME + index; fieldInfo.mixinClassInfo = mixinImpl; addMixinField(fieldInfo, deploymentModel, mixinDef); addMixinMethods(fieldInfo, mixinDef); index++; m_isAdvised = true; } } }
/** * Adds the mixin methods to the target class. * * @param fieldInfo * @param mixinDef */ private void addMixinMethods(final MixinFieldInfo fieldInfo, final MixinDefinition mixinDef) { for (Iterator it3 = mixinDef.getMethodsToIntroduce().iterator(); it3.hasNext(); ) { MethodInfo methodInfo = (MethodInfo) it3.next(); final String methodName = methodInfo.getName(); final String methodSignature = methodInfo.getSignature(); if (m_addedMethods.contains( AlreadyAddedMethodVisitor.getMethodKey(methodName, methodSignature))) { continue; } MethodVisitor mv = cv.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, methodName, methodSignature, null, null); if (fieldInfo.isStatic) { mv.visitFieldInsn( GETSTATIC, m_declaringTypeName, fieldInfo.fieldName, fieldInfo.mixinClassInfo.getSignature()); } else { mv.visitVarInsn(ALOAD, 0); mv.visitFieldInsn( GETFIELD, m_declaringTypeName, fieldInfo.fieldName, fieldInfo.mixinClassInfo.getSignature()); } AsmHelper.loadArgumentTypes(mv, Type.getArgumentTypes(methodSignature), false); mv.visitMethodInsn( INVOKEVIRTUAL, fieldInfo.mixinClassInfo.getName().replace('.', '/'), methodName, methodSignature); AsmHelper.addReturnStatement(mv, Type.getReturnType(methodSignature)); mv.visitMaxs(0, 0); } }