/************************************************************************************** * Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. * * http://aspectwerkz.codehaus.org * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the LGPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package org.codehaus.aspectwerkz.aspect.container; import org.codehaus.aspectwerkz.aspect.AspectContainer; import org.codehaus.aspectwerkz.aspect.management.NoAspectBoundException; import org.codehaus.aspectwerkz.transform.inlining.AsmHelper; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Label; import org.objectweb.asm.Type; /** * Factory compiler for perThis perTarget and perInstance (lazy like) models. * All factories rely on HasInstanceLevelAspect interface. * * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> */ public class PerObjectFactoryCompiler extends AbstractAspectFactoryCompiler { public PerObjectFactoryCompiler(String uuid, String aspectClassName, String aspectQualifiedName, String containerClassName, String rawParameters, ClassLoader loader) { super(uuid, aspectClassName, aspectQualifiedName, containerClassName, rawParameters, loader); } protected void createAspectOf() { MethodVisitor cv = m_cw.visitMethod( ACC_PUBLIC + ACC_STATIC + ACC_FINAL, FACTORY_ASPECTOF_METHOD_NAME, "(Ljava/lang/Object;)" + m_aspectClassSignature, null, null ); // instanceOf check cv.visitVarInsn(ALOAD, 0);// object cv.visitTypeInsn(INSTANCEOF, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME); Label ifInstanceOf = new Label(); cv.visitJumpInsn(IFNE, ifInstanceOf); cv.visitTypeInsn(NEW, Type.getInternalName(NoAspectBoundException.class)); cv.visitInsn(DUP); cv.visitLdcInsn("Unimplemented interface"); cv.visitLdcInsn(m_aspectQualifiedName); cv.visitMethodInsn( INVOKESPECIAL, NO_ASPECT_BOUND_EXCEPTION_CLASS_NAME, INIT_METHOD_NAME, "(Ljava/lang/String;Ljava/lang/String;)V" ); cv.visitInsn(ATHROW); cv.visitLabel(ifInstanceOf); cv.visitVarInsn(ALOAD, 0); cv.visitTypeInsn(CHECKCAST, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME); cv.visitFieldInsn(GETSTATIC, m_aspectFactoryClassName, FACTORY_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE); cv.visitMethodInsn( INVOKEINTERFACE, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME, INSTANCE_LEVEL_GETASPECT_METHOD_NAME, INSTANCE_LEVEL_GETASPECT_METHOD_SIGNATURE ); cv.visitVarInsn(ASTORE, 1); cv.visitVarInsn(ALOAD, 1); Label ifBound = new Label(); cv.visitJumpInsn(IFNONNULL, ifBound); cv.visitTypeInsn(NEW, NO_ASPECT_BOUND_EXCEPTION_CLASS_NAME); cv.visitInsn(DUP); cv.visitLdcInsn("Not bound"); cv.visitLdcInsn(m_aspectQualifiedName); cv.visitMethodInsn( INVOKESPECIAL, NO_ASPECT_BOUND_EXCEPTION_CLASS_NAME, INIT_METHOD_NAME, "(Ljava/lang/String;Ljava/lang/String;)V" ); cv.visitInsn(ATHROW); cv.visitLabel(ifBound); cv.visitVarInsn(ALOAD, 1); cv.visitTypeInsn(CHECKCAST, m_aspectClassName); cv.visitInsn(ARETURN); cv.visitMaxs(0, 0); } protected void createHasAspect() { MethodVisitor cv = m_cw.visitMethod( ACC_PUBLIC + ACC_STATIC, FACTORY_HASASPECT_METHOD_NAME, "(Ljava/lang/Object;)Z", null, null ); // instanceOf check cv.visitVarInsn(ALOAD, 0);// object cv.visitTypeInsn(INSTANCEOF, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME); Label ifInstanceOf = new Label(); cv.visitJumpInsn(IFNE, ifInstanceOf); cv.visitInsn(ICONST_0); cv.visitInsn(IRETURN); cv.visitLabel(ifInstanceOf); cv.visitVarInsn(ALOAD, 0); cv.visitTypeInsn(CHECKCAST, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME); cv.visitFieldInsn(GETSTATIC, m_aspectFactoryClassName, FACTORY_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE); cv.visitMethodInsn( INVOKEINTERFACE, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME, INSTANCE_LEVEL_HASASPECT_METHOD_NAME, INSTANCE_LEVEL_HASASPECT_METHOD_SIGNATURE ); cv.visitInsn(IRETURN); cv.visitMaxs(0, 0); } protected void createOtherArtifacts() { createBindMethod(); } private void createBindMethod() { MethodVisitor cv = m_cw.visitMethod( ACC_PUBLIC + ACC_STATIC + ACC_FINAL, "bind", "(Ljava/lang/Object;)Ljava/lang/Object;", null, null ); // instanceOf check cv.visitVarInsn(ALOAD, 0);// object cv.visitTypeInsn(INSTANCEOF, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME); Label ifInstanceOf = new Label(); cv.visitJumpInsn(IFNE, ifInstanceOf); cv.visitTypeInsn(NEW, NO_ASPECT_BOUND_EXCEPTION_CLASS_NAME); cv.visitInsn(DUP); cv.visitLdcInsn("Unimplemented interface"); cv.visitLdcInsn(m_aspectQualifiedName); cv.visitMethodInsn( INVOKESPECIAL, NO_ASPECT_BOUND_EXCEPTION_CLASS_NAME, INIT_METHOD_NAME, "(Ljava/lang/String;Ljava/lang/String;)V" ); cv.visitInsn(ATHROW); cv.visitLabel(ifInstanceOf); cv.visitVarInsn(ALOAD, 0);//object cv.visitTypeInsn(CHECKCAST, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME); cv.visitFieldInsn(GETSTATIC, m_aspectFactoryClassName, FACTORY_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE); cv.visitMethodInsn( INVOKEINTERFACE, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME, INSTANCE_LEVEL_GETASPECT_METHOD_NAME, INSTANCE_LEVEL_GETASPECT_METHOD_SIGNATURE ); cv.visitVarInsn(ASTORE, 1); cv.visitVarInsn(ALOAD, 1); Label ifAlreadyBound = new Label(); cv.visitJumpInsn(IFNONNULL, ifAlreadyBound); // target instance and arg0 for bind call cv.visitVarInsn(ALOAD, 0);//object cv.visitTypeInsn(CHECKCAST, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME); cv.visitFieldInsn(GETSTATIC, m_aspectFactoryClassName, FACTORY_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE); if (m_hasAspectContainer) { cv.visitFieldInsn( GETSTATIC, m_aspectFactoryClassName, FACTORY_CONTAINER_FIELD_NAME, ASPECT_CONTAINER_CLASS_SIGNATURE ); cv.visitVarInsn(ALOAD, 0);//associated object cv.visitMethodInsn( INVOKEINTERFACE, ASPECT_CONTAINER_CLASS_NAME, ASPECT_CONTAINER_ASPECTOF_METHOD_NAME, "(Ljava/lang/Object;)Ljava/lang/Object;" ); cv.visitTypeInsn(CHECKCAST, m_aspectClassName); } else { cv.visitTypeInsn(NEW, m_aspectClassName); cv.visitInsn(DUP); cv.visitMethodInsn(INVOKESPECIAL, m_aspectClassName, INIT_METHOD_NAME, NO_PARAM_RETURN_VOID_SIGNATURE); } cv.visitMethodInsn( INVOKEINTERFACE, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME, INSTANCE_LEVEL_BINDASPECT_METHOD_NAME, INSTANCE_LEVEL_BINDASPECT_METHOD_SIGNATURE ); cv.visitInsn(ARETURN); cv.visitLabel(ifAlreadyBound); cv.visitVarInsn(ALOAD, 1); cv.visitInsn(ARETURN); cv.visitMaxs(0, 0); } public static class PerInstanceFactoryCompiler extends PerObjectFactoryCompiler { public PerInstanceFactoryCompiler(String uuid, String aspectClassName, String aspectQualifiedName, String containerClassName, String rawParameters, ClassLoader loader) { super(uuid, aspectClassName, aspectQualifiedName, containerClassName, rawParameters, loader); } protected void createAspectOf() { MethodVisitor cv = m_cw.visitMethod( ACC_PUBLIC + ACC_STATIC + ACC_FINAL, FACTORY_ASPECTOF_METHOD_NAME, "(Ljava/lang/Object;)" + m_aspectClassSignature, null, null ); // instanceOf check cv.visitVarInsn(ALOAD, 0);// object cv.visitTypeInsn(INSTANCEOF, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME); Label ifInstanceOf = new Label(); cv.visitJumpInsn(IFNE, ifInstanceOf); cv.visitTypeInsn(NEW, Type.getInternalName(NoAspectBoundException.class)); cv.visitInsn(DUP); cv.visitLdcInsn("Unimplemented interface"); cv.visitLdcInsn(m_aspectQualifiedName); cv.visitMethodInsn( INVOKESPECIAL, NO_ASPECT_BOUND_EXCEPTION_CLASS_NAME, INIT_METHOD_NAME, "(Ljava/lang/String;Ljava/lang/String;)V" ); cv.visitInsn(ATHROW); cv.visitLabel(ifInstanceOf); cv.visitVarInsn(ALOAD, 0); cv.visitTypeInsn(CHECKCAST, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME); cv.visitFieldInsn(GETSTATIC, m_aspectFactoryClassName, FACTORY_CLASS_FIELD_NAME, CLASS_CLASS_SIGNATURE); cv.visitMethodInsn( INVOKEINTERFACE, HAS_INSTANCE_LEVEL_ASPECT_INTERFACE_NAME, INSTANCE_LEVEL_GETASPECT_METHOD_NAME, INSTANCE_LEVEL_GETASPECT_METHOD_SIGNATURE ); cv.visitVarInsn(ASTORE, 1); cv.visitVarInsn(ALOAD, 1); Label ifBound = new Label(); cv.visitJumpInsn(IFNONNULL, ifBound); // no aspect bound yet - since perInstance is lazy delegate to bind cv.visitVarInsn(ALOAD, 0); cv.visitMethodInsn( INVOKESTATIC, m_aspectFactoryClassName, "bind", "(Ljava/lang/Object;)Ljava/lang/Object;" ); cv.visitVarInsn(ASTORE, 1); cv.visitLabel(ifBound); cv.visitVarInsn(ALOAD, 1); cv.visitTypeInsn(CHECKCAST, m_aspectClassName); cv.visitInsn(ARETURN); cv.visitMaxs(0, 0); } } }