/************************************************************************************** * 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.transform.inlining.weaver; import org.objectweb.asm.MethodAdapter; import org.objectweb.asm.MethodVisitor; import org.codehaus.aspectwerkz.transform.TransformationConstants; import org.codehaus.aspectwerkz.transform.inlining.AsmNullAdapter; /** * A visitor that keeps track of NEW and INVOKESPECIAL when within a constructor * to flag when the object initialization has been reached (after this/super call). * <p/> * No regular weaving should occur before it since this(XXJP.invoke(this)) is not allowed Java code * * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a> */ public class AfterObjectInitializationCodeAdapter extends MethodAdapter implements TransformationConstants { private String m_callerMemberName; private int m_newCount = 0; private int m_invokeSpecialCount = 0; protected boolean m_isObjectInitialized = false; public AfterObjectInitializationCodeAdapter(MethodVisitor cv, String callerMemberName) { super(cv); m_callerMemberName = callerMemberName; // object initialization matters within constructors only if (!m_callerMemberName.equals(INIT_METHOD_NAME)) { m_isObjectInitialized = true; } } public void visitTypeInsn(int opcode, String desc) { if (opcode == NEW) { m_newCount++; } super.visitTypeInsn(opcode, desc); } protected boolean queryCurrentMethodInsn(final int opcode, final String calleeClassName, final String calleeMethodName, final String calleeMethodDesc) { int localInvokeSpecialCount = m_invokeSpecialCount; int localNewCount = m_newCount; if (opcode == INVOKESPECIAL) { localInvokeSpecialCount++; } if (m_callerMemberName.equals(INIT_METHOD_NAME)) { // in ctor // make sure we are after object initialization ie after // the INVOKESPECIAL for this(..) / super(..) // that is we have seen an INVOKESPECIAL while newCount == 0 // or while newCount == invokeSpecialCount - 1 // [ ie same with numberOfInvokeSpecialCount = 1 ] if (opcode == INVOKESPECIAL) { if (localNewCount == localInvokeSpecialCount -1) { return true; } } return false; } return false; } public void visitMethodInsn(final int opcode, final String calleeClassName, final String calleeMethodName, final String calleeMethodDesc) { if (opcode == INVOKESPECIAL) { m_invokeSpecialCount++; } if (m_callerMemberName.equals(INIT_METHOD_NAME)) { // in ctor // make sure we are after object initialization ie after // the INVOKESPECIAL for this(..) / super(..) // that is we have seen an INVOKESPECIAL while newCount == 0 // or while newCount == invokeSpecialCount - 1 // [ ie same with numberOfInvokeSpecialCount = 1 ] if (opcode == INVOKESPECIAL) { if (m_newCount == m_invokeSpecialCount -1) { m_isObjectInitialized = true; } } } super.visitMethodInsn(opcode, calleeClassName, calleeMethodName, calleeMethodDesc); } }